@apex-inc/capacitor-plugin 0.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.
Files changed (83) hide show
  1. package/ApexCapacitorPlugin.podspec +17 -0
  2. package/LICENSE +17 -0
  3. package/README.md +136 -0
  4. package/android/build.gradle +68 -0
  5. package/android/src/main/AndroidManifest.xml +8 -0
  6. package/android/src/main/java/inc/apex/capacitor/ApexCapacitorPlugin.kt +325 -0
  7. package/android/src/main/java/inc/apex/capacitor/DeepLinkManager.kt +47 -0
  8. package/android/src/main/java/inc/apex/capacitor/InstallReferrerParser.kt +123 -0
  9. package/android/src/main/java/inc/apex/capacitor/OfflineQueue.kt +150 -0
  10. package/android/src/main/java/inc/apex/capacitor/SessionManager.kt +108 -0
  11. package/dist/batch-sender.d.ts +60 -0
  12. package/dist/batch-sender.d.ts.map +1 -0
  13. package/dist/batch-sender.js +115 -0
  14. package/dist/batch-sender.js.map +1 -0
  15. package/dist/definitions.d.ts +224 -0
  16. package/dist/definitions.d.ts.map +1 -0
  17. package/dist/definitions.js +14 -0
  18. package/dist/definitions.js.map +1 -0
  19. package/dist/esm/batch-sender.d.ts +60 -0
  20. package/dist/esm/batch-sender.d.ts.map +1 -0
  21. package/dist/esm/batch-sender.js +111 -0
  22. package/dist/esm/batch-sender.js.map +1 -0
  23. package/dist/esm/definitions.d.ts +224 -0
  24. package/dist/esm/definitions.d.ts.map +1 -0
  25. package/dist/esm/definitions.js +13 -0
  26. package/dist/esm/definitions.js.map +1 -0
  27. package/dist/esm/event-id.d.ts +17 -0
  28. package/dist/esm/event-id.d.ts.map +1 -0
  29. package/dist/esm/event-id.js +57 -0
  30. package/dist/esm/event-id.js.map +1 -0
  31. package/dist/esm/index.d.ts +29 -0
  32. package/dist/esm/index.d.ts.map +1 -0
  33. package/dist/esm/index.js +30 -0
  34. package/dist/esm/index.js.map +1 -0
  35. package/dist/esm/offline-queue.d.ts +111 -0
  36. package/dist/esm/offline-queue.d.ts.map +1 -0
  37. package/dist/esm/offline-queue.js +240 -0
  38. package/dist/esm/offline-queue.js.map +1 -0
  39. package/dist/esm/session-manager.d.ts +63 -0
  40. package/dist/esm/session-manager.d.ts.map +1 -0
  41. package/dist/esm/session-manager.js +100 -0
  42. package/dist/esm/session-manager.js.map +1 -0
  43. package/dist/esm/web.d.ts +65 -0
  44. package/dist/esm/web.d.ts.map +1 -0
  45. package/dist/esm/web.js +203 -0
  46. package/dist/esm/web.js.map +1 -0
  47. package/dist/event-id.d.ts +17 -0
  48. package/dist/event-id.d.ts.map +1 -0
  49. package/dist/event-id.js +61 -0
  50. package/dist/event-id.js.map +1 -0
  51. package/dist/index.d.ts +29 -0
  52. package/dist/index.d.ts.map +1 -0
  53. package/dist/index.js +76 -0
  54. package/dist/index.js.map +1 -0
  55. package/dist/offline-queue.d.ts +111 -0
  56. package/dist/offline-queue.d.ts.map +1 -0
  57. package/dist/offline-queue.js +246 -0
  58. package/dist/offline-queue.js.map +1 -0
  59. package/dist/session-manager.d.ts +63 -0
  60. package/dist/session-manager.d.ts.map +1 -0
  61. package/dist/session-manager.js +104 -0
  62. package/dist/session-manager.js.map +1 -0
  63. package/dist/web.d.ts +65 -0
  64. package/dist/web.d.ts.map +1 -0
  65. package/dist/web.js +207 -0
  66. package/dist/web.js.map +1 -0
  67. package/ios/Package.swift +34 -0
  68. package/ios/Sources/ApexCapacitorPlugin/AdvertisingIdProvider.swift +66 -0
  69. package/ios/Sources/ApexCapacitorPlugin/AttManager.swift +82 -0
  70. package/ios/Sources/ApexCapacitorPlugin/DeepLinkManager.swift +64 -0
  71. package/ios/Sources/ApexCapacitorPlugin/DeviceInfo.swift +107 -0
  72. package/ios/Sources/ApexCapacitorPlugin/OfflineQueue.swift +191 -0
  73. package/ios/Sources/ApexCapacitorPlugin/SessionManager.swift +113 -0
  74. package/ios/Sources/ApexCapacitorPlugin/SkanManager.swift +95 -0
  75. package/ios/Sources/ApexCapacitorPluginBridge/ApexCapacitorPlugin.swift +269 -0
  76. package/ios/Tests/ApexCapacitorPluginTests/AdvertisingIdProviderTests.swift +74 -0
  77. package/ios/Tests/ApexCapacitorPluginTests/AttManagerTests.swift +82 -0
  78. package/ios/Tests/ApexCapacitorPluginTests/DeepLinkManagerTests.swift +69 -0
  79. package/ios/Tests/ApexCapacitorPluginTests/DeviceInfoTests.swift +52 -0
  80. package/ios/Tests/ApexCapacitorPluginTests/OfflineQueueTests.swift +134 -0
  81. package/ios/Tests/ApexCapacitorPluginTests/SessionManagerTests.swift +98 -0
  82. package/ios/Tests/ApexCapacitorPluginTests/SkanManagerTests.swift +91 -0
  83. package/package.json +82 -0
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Mobile session manager.
3
+ *
4
+ * Defines the boundaries of a user's interaction with the app. A session
5
+ * starts on the first event after inactivity and ends when either
6
+ * (a) no events arrive for `timeoutMinutes` (default 30), or
7
+ * (b) the app is force-backgrounded and the OS reclaims memory.
8
+ *
9
+ * Emits `session_start` and `session_end` events that plug directly into the
10
+ * server's MSESSION# rollup (Phase 1c). The timeout is configurable and the
11
+ * clock is injectable for deterministic testing.
12
+ */
13
+ import { generateEventId } from "./event-id";
14
+ export class SessionManager {
15
+ constructor(options = {}) {
16
+ this.current = null;
17
+ this.timeoutHandle = null;
18
+ this.timeoutMs = (options.timeoutMinutes ?? 30) * 60 * 1000;
19
+ this.onSessionStart = options.onSessionStart;
20
+ this.onSessionEnd = options.onSessionEnd;
21
+ this.now = options.now ?? (() => Date.now());
22
+ const defaultScheduler = {
23
+ setTimeout: (cb, ms) => setTimeout(cb, ms),
24
+ clearTimeout: (handle) => clearTimeout(handle),
25
+ };
26
+ const scheduler = options.scheduler ?? defaultScheduler;
27
+ this.setTimeoutFn = scheduler.setTimeout;
28
+ this.clearTimeoutFn = scheduler.clearTimeout;
29
+ }
30
+ /**
31
+ * Records user activity. Starts a new session if none is active, otherwise
32
+ * resets the inactivity timeout. Returns the current session snapshot.
33
+ */
34
+ recordActivity() {
35
+ const nowMs = this.now();
36
+ const isoNow = new Date(nowMs).toISOString();
37
+ if (!this.current) {
38
+ this.current = {
39
+ sessionId: generateEventId(),
40
+ startedAt: isoNow,
41
+ lastActivityAt: isoNow,
42
+ eventCount: 1,
43
+ };
44
+ if (this.onSessionStart)
45
+ this.onSessionStart({ ...this.current });
46
+ }
47
+ else {
48
+ this.current = {
49
+ ...this.current,
50
+ lastActivityAt: isoNow,
51
+ eventCount: this.current.eventCount + 1,
52
+ };
53
+ }
54
+ this.scheduleTimeout();
55
+ return { ...this.current };
56
+ }
57
+ /**
58
+ * Explicitly ends the current session immediately. Fires `onSessionEnd`.
59
+ * No-op if no session is active.
60
+ */
61
+ endSession() {
62
+ if (!this.current)
63
+ return;
64
+ this.clearTimeout();
65
+ const nowMs = this.now();
66
+ const startedMs = Date.parse(this.current.startedAt);
67
+ const durationSeconds = Math.max(0, Math.floor((nowMs - startedMs) / 1000));
68
+ const ended = {
69
+ ...this.current,
70
+ endedAt: new Date(nowMs).toISOString(),
71
+ durationSeconds,
72
+ };
73
+ if (this.onSessionEnd)
74
+ this.onSessionEnd(ended);
75
+ this.current = null;
76
+ }
77
+ /** Returns the current session snapshot, or null. */
78
+ getCurrent() {
79
+ return this.current ? { ...this.current } : null;
80
+ }
81
+ /** Force-starts a new session, ending any current one. */
82
+ forceStart() {
83
+ if (this.current)
84
+ this.endSession();
85
+ return this.recordActivity();
86
+ }
87
+ scheduleTimeout() {
88
+ this.clearTimeout();
89
+ this.timeoutHandle = this.setTimeoutFn(() => {
90
+ this.endSession();
91
+ }, this.timeoutMs);
92
+ }
93
+ clearTimeout() {
94
+ if (this.timeoutHandle !== null) {
95
+ this.clearTimeoutFn(this.timeoutHandle);
96
+ this.timeoutHandle = null;
97
+ }
98
+ }
99
+ }
100
+ //# sourceMappingURL=session-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-manager.js","sourceRoot":"","sources":["../../src/session-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Web fallback implementation of `ApexCapacitorPlugin`.
3
+ *
4
+ * Runs when the app is in a browser or Capacitor PWA context where no native
5
+ * iOS/Android bridge is present. Provides best-effort behavior for every
6
+ * method — identifiers return null, ATT is a no-op (returns `authorized`),
7
+ * SKAN is a no-op, deep links come from `window.location`, and events are
8
+ * batched + sent over fetch via the normal offline queue.
9
+ *
10
+ * This module deliberately keeps the heavy lifting (queue, session, batch)
11
+ * in separate files so unit tests can cover them without DOM mocking.
12
+ */
13
+ import { WebPlugin } from "@capacitor/core";
14
+ import type { AdvertisingIdResult, ApexCapacitorPlugin, ApexEvent, AttStatus, DeviceInfo, FlushResult, InitializeOptions, QueueStatus, SessionInfo, SkanCoarseValue } from "./definitions";
15
+ export declare class ApexCapacitorWeb extends WebPlugin implements ApexCapacitorPlugin {
16
+ private queue?;
17
+ private session?;
18
+ private sender?;
19
+ private visitorId?;
20
+ private testMode;
21
+ private debug;
22
+ private initialized;
23
+ initialize(options: InitializeOptions): Promise<void>;
24
+ requestTrackingAuthorization(): Promise<{
25
+ status: AttStatus;
26
+ }>;
27
+ getTrackingStatus(): Promise<{
28
+ status: AttStatus;
29
+ }>;
30
+ getAdvertisingId(): Promise<AdvertisingIdResult>;
31
+ getInstallReferrer(): Promise<{
32
+ referrer: string | null;
33
+ }>;
34
+ getVisitorId(): Promise<{
35
+ visitorId: string;
36
+ }>;
37
+ setVisitorId(options: {
38
+ visitorId: string;
39
+ }): Promise<void>;
40
+ updateConversionValue(_options: {
41
+ fineValue: number;
42
+ coarseValue?: SkanCoarseValue;
43
+ }): Promise<void>;
44
+ getInitialDeepLink(): Promise<{
45
+ url: string | null;
46
+ }>;
47
+ getDeviceInfo(): Promise<DeviceInfo>;
48
+ startSession(): Promise<{
49
+ sessionId: string;
50
+ }>;
51
+ endSession(): Promise<void>;
52
+ getCurrentSession(): Promise<SessionInfo>;
53
+ track(event: ApexEvent): Promise<void>;
54
+ getQueueSize(): Promise<QueueStatus>;
55
+ flushQueue(): Promise<FlushResult>;
56
+ setTestMode(options: {
57
+ enabled: boolean;
58
+ }): Promise<void>;
59
+ removeAllListeners(): Promise<void>;
60
+ private emitSession;
61
+ private loadOrCreateVisitorId;
62
+ private saveVisitorId;
63
+ private ensureInitialized;
64
+ }
65
+ //# sourceMappingURL=web.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web.d.ts","sourceRoot":"","sources":["../../src/web.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,KAAK,EACV,mBAAmB,EACnB,mBAAmB,EACnB,SAAS,EACT,SAAS,EACT,UAAU,EACV,WAAW,EACX,iBAAiB,EACjB,WAAW,EACX,WAAW,EACX,eAAe,EAChB,MAAM,eAAe,CAAC;AAQvB,qBAAa,gBAAiB,SAAQ,SAAU,YAAW,mBAAmB;IAC5E,OAAO,CAAC,KAAK,CAAC,CAAe;IAC7B,OAAO,CAAC,OAAO,CAAC,CAAiB;IACjC,OAAO,CAAC,MAAM,CAAC,CAAc;IAC7B,OAAO,CAAC,SAAS,CAAC,CAAS;IAC3B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,WAAW,CAAS;IAEtB,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAiCrD,4BAA4B,IAAI,OAAO,CAAC;QAAE,MAAM,EAAE,SAAS,CAAA;KAAE,CAAC;IAI9D,iBAAiB,IAAI,OAAO,CAAC;QAAE,MAAM,EAAE,SAAS,CAAA;KAAE,CAAC;IAInD,gBAAgB,IAAI,OAAO,CAAC,mBAAmB,CAAC;IAIhD,kBAAkB,IAAI,OAAO,CAAC;QAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;IAI1D,YAAY,IAAI,OAAO,CAAC;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAO9C,YAAY,CAAC,OAAO,EAAE;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAK3D,qBAAqB,CAAC,QAAQ,EAAE;QACpC,SAAS,EAAE,MAAM,CAAC;QAClB,WAAW,CAAC,EAAE,eAAe,CAAC;KAC/B,GAAG,OAAO,CAAC,IAAI,CAAC;IAIX,kBAAkB,IAAI,OAAO,CAAC;QAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;IAOrD,aAAa,IAAI,OAAO,CAAC,UAAU,CAAC;IAiBpC,YAAY,IAAI,OAAO,CAAC;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAM9C,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAK3B,iBAAiB,IAAI,OAAO,CAAC,WAAW,CAAC;IAQzC,KAAK,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IA2BtC,YAAY,IAAI,OAAO,CAAC,WAAW,CAAC;IASpC,UAAU,IAAI,OAAO,CAAC,WAAW,CAAC;IAMlC,WAAW,CAAC,OAAO,EAAE;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAIzD,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC;IAIzC,OAAO,CAAC,WAAW;IAcnB,OAAO,CAAC,qBAAqB;IAe7B,OAAO,CAAC,aAAa;IAUrB,OAAO,CAAC,iBAAiB;CAK1B"}
@@ -0,0 +1,203 @@
1
+ /**
2
+ * Web fallback implementation of `ApexCapacitorPlugin`.
3
+ *
4
+ * Runs when the app is in a browser or Capacitor PWA context where no native
5
+ * iOS/Android bridge is present. Provides best-effort behavior for every
6
+ * method — identifiers return null, ATT is a no-op (returns `authorized`),
7
+ * SKAN is a no-op, deep links come from `window.location`, and events are
8
+ * batched + sent over fetch via the normal offline queue.
9
+ *
10
+ * This module deliberately keeps the heavy lifting (queue, session, batch)
11
+ * in separate files so unit tests can cover them without DOM mocking.
12
+ */
13
+ import { WebPlugin } from "@capacitor/core";
14
+ import { BatchSender } from "./batch-sender";
15
+ import { generateEventId, isValidEventId } from "./event-id";
16
+ import { IndexedDBStorage, InMemoryStorage, OfflineQueue } from "./offline-queue";
17
+ import { SessionManager } from "./session-manager";
18
+ const VISITOR_ID_KEY = "apex.visitorId";
19
+ export class ApexCapacitorWeb extends WebPlugin {
20
+ constructor() {
21
+ super(...arguments);
22
+ this.testMode = false;
23
+ this.debug = false;
24
+ this.initialized = false;
25
+ }
26
+ async initialize(options) {
27
+ if (this.initialized)
28
+ return;
29
+ this.testMode = options.testMode ?? false;
30
+ this.debug = options.debug ?? false;
31
+ const storage = typeof indexedDB !== "undefined" ? new IndexedDBStorage() : new InMemoryStorage();
32
+ this.queue = new OfflineQueue({
33
+ storage,
34
+ maxSize: options.offlineQueueMaxSize ?? 1000,
35
+ onEvicted: (ev) => {
36
+ if (this.debug)
37
+ console.warn("[apex-capacitor] queue eviction", ev.event.id);
38
+ },
39
+ });
40
+ this.session = new SessionManager({
41
+ timeoutMinutes: options.sessionTimeoutMinutes ?? 30,
42
+ onSessionStart: (s) => this.emitSession("sessionStart", s),
43
+ onSessionEnd: (s) => this.emitSession("sessionEnd", s),
44
+ });
45
+ this.sender = new BatchSender({
46
+ apiUrl: options.apiUrl,
47
+ projectKey: options.projectKey,
48
+ platformHeader: "web",
49
+ debug: this.debug,
50
+ });
51
+ this.visitorId = this.loadOrCreateVisitorId();
52
+ this.initialized = true;
53
+ }
54
+ async requestTrackingAuthorization() {
55
+ return { status: "authorized" };
56
+ }
57
+ async getTrackingStatus() {
58
+ return { status: "authorized" };
59
+ }
60
+ async getAdvertisingId() {
61
+ return { id: null, fallback: null };
62
+ }
63
+ async getInstallReferrer() {
64
+ return { referrer: null };
65
+ }
66
+ async getVisitorId() {
67
+ if (!this.visitorId) {
68
+ this.visitorId = this.loadOrCreateVisitorId();
69
+ }
70
+ return { visitorId: this.visitorId };
71
+ }
72
+ async setVisitorId(options) {
73
+ this.visitorId = options.visitorId;
74
+ this.saveVisitorId(options.visitorId);
75
+ }
76
+ async updateConversionValue(_options) {
77
+ // No-op on web / non-iOS.
78
+ }
79
+ async getInitialDeepLink() {
80
+ if (typeof window !== "undefined" && window.location) {
81
+ return { url: window.location.href };
82
+ }
83
+ return { url: null };
84
+ }
85
+ async getDeviceInfo() {
86
+ // Best-effort on web — mostly placeholders so callers get consistent shape.
87
+ const ua = typeof navigator !== "undefined" ? navigator.userAgent : "";
88
+ const locale = typeof navigator !== "undefined" ? navigator.language : "en-US";
89
+ const tz = typeof Intl !== "undefined" ? Intl.DateTimeFormat().resolvedOptions().timeZone : "UTC";
90
+ return {
91
+ platform: "android", // Web falls back to android shape; native overrides when present.
92
+ osVersion: "unknown",
93
+ model: ua.substring(0, 64),
94
+ appVersion: "0.0.0",
95
+ bundleId: typeof location !== "undefined" ? location.host : "web",
96
+ timezone: tz,
97
+ locale,
98
+ };
99
+ }
100
+ async startSession() {
101
+ this.ensureInitialized();
102
+ const snapshot = this.session.forceStart();
103
+ return { sessionId: snapshot.sessionId };
104
+ }
105
+ async endSession() {
106
+ if (!this.session)
107
+ return;
108
+ this.session.endSession();
109
+ }
110
+ async getCurrentSession() {
111
+ const current = this.session?.getCurrent() ?? null;
112
+ return {
113
+ sessionId: current?.sessionId ?? null,
114
+ startedAt: current?.startedAt ?? null,
115
+ };
116
+ }
117
+ async track(event) {
118
+ this.ensureInitialized();
119
+ const sessionSnapshot = this.session.recordActivity();
120
+ const stamped = {
121
+ ...event,
122
+ id: event.id ?? generateEventId(),
123
+ timestamp: event.timestamp ?? new Date().toISOString(),
124
+ sessionId: event.sessionId ?? sessionSnapshot.sessionId,
125
+ };
126
+ if (this.testMode) {
127
+ stamped.data = { ...(stamped.data ?? {}), __testMode: true };
128
+ }
129
+ if (stamped.id && !isValidEventId(stamped.id)) {
130
+ // Developer mis-set id — overwrite rather than fail the track() call.
131
+ if (this.debug)
132
+ console.warn("[apex-capacitor] invalid event.id, regenerating");
133
+ stamped.id = generateEventId();
134
+ }
135
+ await this.queue.enqueue(stamped);
136
+ // Attempt delivery; errors are swallowed — events stay queued for next flush.
137
+ void this.sender.flush(this.queue).catch((err) => {
138
+ if (this.debug)
139
+ console.warn("[apex-capacitor] flush error", err);
140
+ });
141
+ }
142
+ async getQueueSize() {
143
+ if (!this.queue)
144
+ return { count: 0, oldestEventAt: null };
145
+ const [count, oldestEventAt] = await Promise.all([
146
+ this.queue.size(),
147
+ this.queue.oldestEventAt(),
148
+ ]);
149
+ return { count, oldestEventAt };
150
+ }
151
+ async flushQueue() {
152
+ this.ensureInitialized();
153
+ const result = await this.sender.flush(this.queue);
154
+ return { flushed: result.flushed, remaining: result.remaining };
155
+ }
156
+ async setTestMode(options) {
157
+ this.testMode = options.enabled;
158
+ }
159
+ async removeAllListeners() {
160
+ await super.removeAllListeners();
161
+ }
162
+ emitSession(eventName, session) {
163
+ const payload = eventName === "sessionStart"
164
+ ? { sessionId: session.sessionId }
165
+ : {
166
+ sessionId: session.sessionId,
167
+ durationSeconds: session.durationSeconds ?? 0,
168
+ };
169
+ this.notifyListeners(eventName, payload);
170
+ }
171
+ loadOrCreateVisitorId() {
172
+ if (typeof localStorage !== "undefined") {
173
+ const existing = localStorage.getItem(VISITOR_ID_KEY);
174
+ if (existing)
175
+ return existing;
176
+ const fresh = generateEventId();
177
+ try {
178
+ localStorage.setItem(VISITOR_ID_KEY, fresh);
179
+ }
180
+ catch {
181
+ // Storage quota / private mode — fall through to in-memory.
182
+ }
183
+ return fresh;
184
+ }
185
+ return generateEventId();
186
+ }
187
+ saveVisitorId(id) {
188
+ if (typeof localStorage !== "undefined") {
189
+ try {
190
+ localStorage.setItem(VISITOR_ID_KEY, id);
191
+ }
192
+ catch {
193
+ // ignore
194
+ }
195
+ }
196
+ }
197
+ ensureInitialized() {
198
+ if (!this.initialized || !this.queue || !this.session || !this.sender) {
199
+ throw new Error("Apex plugin not initialized. Call initialize() before using other methods.");
200
+ }
201
+ }
202
+ }
203
+ //# sourceMappingURL=web.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/web.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * UUIDv4 generator for client-assigned event IDs.
3
+ *
4
+ * Used by the Apex Capacitor plugin to stamp every event with an idempotency
5
+ * key before it hits the network. The server dedupes on this ID within a
6
+ * 24-hour window — without it, mobile retry storms would double-count installs
7
+ * and waste client ad budget.
8
+ *
9
+ * Prefers `crypto.randomUUID()` when available (modern browsers, Node 14.17+,
10
+ * Capacitor WebViews on iOS 14+/Android 10+). Falls back to a manual
11
+ * implementation using `crypto.getRandomValues` for older environments.
12
+ */
13
+ /** Generates a RFC 4122 v4 UUID. */
14
+ export declare function generateEventId(): string;
15
+ /** Validates a string looks like a UUIDv4. Useful in tests and sanity checks. */
16
+ export declare function isValidEventId(value: string): boolean;
17
+ //# sourceMappingURL=event-id.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-id.d.ts","sourceRoot":"","sources":["../src/event-id.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,oCAAoC;AACpC,wBAAgB,eAAe,IAAI,MAAM,CAcxC;AAED,iFAAiF;AACjF,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAErD"}
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ /**
3
+ * UUIDv4 generator for client-assigned event IDs.
4
+ *
5
+ * Used by the Apex Capacitor plugin to stamp every event with an idempotency
6
+ * key before it hits the network. The server dedupes on this ID within a
7
+ * 24-hour window — without it, mobile retry storms would double-count installs
8
+ * and waste client ad budget.
9
+ *
10
+ * Prefers `crypto.randomUUID()` when available (modern browsers, Node 14.17+,
11
+ * Capacitor WebViews on iOS 14+/Android 10+). Falls back to a manual
12
+ * implementation using `crypto.getRandomValues` for older environments.
13
+ */
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.generateEventId = generateEventId;
16
+ exports.isValidEventId = isValidEventId;
17
+ /** Generates a RFC 4122 v4 UUID. */
18
+ function generateEventId() {
19
+ const g = globalThis;
20
+ if (g.crypto && typeof g.crypto.randomUUID === "function") {
21
+ return g.crypto.randomUUID();
22
+ }
23
+ if (g.crypto && typeof g.crypto.getRandomValues === "function") {
24
+ return generateUuidFromRandomBytes(g.crypto);
25
+ }
26
+ // Last-resort fallback: Math.random() (not cryptographically secure, but
27
+ // still satisfies the uniqueness requirement at our scale).
28
+ return generateUuidFromMath();
29
+ }
30
+ /** Validates a string looks like a UUIDv4. Useful in tests and sanity checks. */
31
+ function isValidEventId(value) {
32
+ return /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(value);
33
+ }
34
+ function generateUuidFromRandomBytes(crypto) {
35
+ const bytes = new Uint8Array(16);
36
+ crypto.getRandomValues(bytes);
37
+ // Set version (4) and variant (RFC 4122) bits.
38
+ bytes[6] = (bytes[6] & 0x0f) | 0x40;
39
+ bytes[8] = (bytes[8] & 0x3f) | 0x80;
40
+ const hex = [];
41
+ for (let i = 0; i < bytes.length; i++) {
42
+ hex.push(bytes[i].toString(16).padStart(2, "0"));
43
+ }
44
+ return (hex.slice(0, 4).join("") +
45
+ "-" +
46
+ hex.slice(4, 6).join("") +
47
+ "-" +
48
+ hex.slice(6, 8).join("") +
49
+ "-" +
50
+ hex.slice(8, 10).join("") +
51
+ "-" +
52
+ hex.slice(10, 16).join(""));
53
+ }
54
+ function generateUuidFromMath() {
55
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
56
+ const r = (Math.random() * 16) | 0;
57
+ const v = c === "x" ? r : (r & 0x3) | 0x8;
58
+ return v.toString(16);
59
+ });
60
+ }
61
+ //# sourceMappingURL=event-id.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-id.js","sourceRoot":"","sources":["../src/event-id.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;GAWG;;AAGH,0CAcC;AAGD,wCAEC;AApBD,oCAAoC;AACpC,SAAgB,eAAe;IAC7B,MAAM,CAAC,GAAG,UAAiC,CAAC;IAE5C,IAAI,CAAC,CAAC,MAAM,IAAI,OAAO,CAAC,CAAC,MAAM,CAAC,UAAU,KAAK,UAAU,EAAE,CAAC;QAC1D,OAAO,CAAC,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;IAC/B,CAAC;IAED,IAAI,CAAC,CAAC,MAAM,IAAI,OAAO,CAAC,CAAC,MAAM,CAAC,eAAe,KAAK,UAAU,EAAE,CAAC;QAC/D,OAAO,2BAA2B,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IAC/C,CAAC;IAED,yEAAyE;IACzE,4DAA4D;IAC5D,OAAO,oBAAoB,EAAE,CAAC;AAChC,CAAC;AAED,iFAAiF;AACjF,SAAgB,cAAc,CAAC,KAAa;IAC1C,OAAO,wEAAwE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC9F,CAAC;AAED,SAAS,2BAA2B,CAAC,MAAc;IACjD,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,EAAE,CAAC,CAAC;IACjC,MAAM,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;IAC9B,+CAA+C;IAC/C,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;IACpC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;IAEpC,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;IACnD,CAAC;IACD,OAAO,CACL,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;QACxB,GAAG;QACH,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;QACxB,GAAG;QACH,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;QACxB,GAAG;QACH,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;QACzB,GAAG;QACH,GAAG,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAC3B,CAAC;AACJ,CAAC;AAED,SAAS,oBAAoB;IAC3B,OAAO,sCAAsC,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE;QACnE,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC;QACnC,MAAM,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC;QAC1C,OAAO,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IACxB,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Public entry point for `@apex-inc/capacitor-plugin`.
3
+ *
4
+ * Registers the plugin with Capacitor's plugin registry and exports the
5
+ * proxy. Consumers import like:
6
+ *
7
+ * ```ts
8
+ * import { Apex } from "@apex-inc/capacitor-plugin";
9
+ *
10
+ * await Apex.initialize({ projectKey: "prj_..." });
11
+ * await Apex.track({ type: "app_open" });
12
+ * ```
13
+ */
14
+ import type { ApexCapacitorPlugin } from "./definitions";
15
+ /**
16
+ * Capacitor plugin proxy. In a native app, calls route through the bridge to
17
+ * the iOS (Swift) or Android (Kotlin) implementation. In a web context
18
+ * (browser or Capacitor PWA), the web fallback in `./web.ts` takes over.
19
+ */
20
+ export declare const Apex: ApexCapacitorPlugin;
21
+ export * from "./definitions";
22
+ export { OfflineQueue, InMemoryStorage, IndexedDBStorage } from "./offline-queue";
23
+ export type { OfflineQueueStorage, OfflineQueueOptions, QueuedEvent } from "./offline-queue";
24
+ export { SessionManager } from "./session-manager";
25
+ export type { SessionManagerOptions, SessionSnapshot } from "./session-manager";
26
+ export { BatchSender } from "./batch-sender";
27
+ export type { BatchSenderOptions, FlushResult as BatchFlushResult } from "./batch-sender";
28
+ export { generateEventId, isValidEventId } from "./event-id";
29
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAEzD;;;;GAIG;AACH,eAAO,MAAM,IAAI,EAAE,mBAKlB,CAAC;AAGF,cAAc,eAAe,CAAC;AAG9B,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAClF,YAAY,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC7F,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,YAAY,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAChF,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,YAAY,EAAE,kBAAkB,EAAE,WAAW,IAAI,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAC1F,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ /**
3
+ * Public entry point for `@apex-inc/capacitor-plugin`.
4
+ *
5
+ * Registers the plugin with Capacitor's plugin registry and exports the
6
+ * proxy. Consumers import like:
7
+ *
8
+ * ```ts
9
+ * import { Apex } from "@apex-inc/capacitor-plugin";
10
+ *
11
+ * await Apex.initialize({ projectKey: "prj_..." });
12
+ * await Apex.track({ type: "app_open" });
13
+ * ```
14
+ */
15
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
16
+ if (k2 === undefined) k2 = k;
17
+ var desc = Object.getOwnPropertyDescriptor(m, k);
18
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
19
+ desc = { enumerable: true, get: function() { return m[k]; } };
20
+ }
21
+ Object.defineProperty(o, k2, desc);
22
+ }) : (function(o, m, k, k2) {
23
+ if (k2 === undefined) k2 = k;
24
+ o[k2] = m[k];
25
+ }));
26
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
27
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
28
+ }) : function(o, v) {
29
+ o["default"] = v;
30
+ });
31
+ var __importStar = (this && this.__importStar) || (function () {
32
+ var ownKeys = function(o) {
33
+ ownKeys = Object.getOwnPropertyNames || function (o) {
34
+ var ar = [];
35
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
36
+ return ar;
37
+ };
38
+ return ownKeys(o);
39
+ };
40
+ return function (mod) {
41
+ if (mod && mod.__esModule) return mod;
42
+ var result = {};
43
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
44
+ __setModuleDefault(result, mod);
45
+ return result;
46
+ };
47
+ })();
48
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
49
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
50
+ };
51
+ Object.defineProperty(exports, "__esModule", { value: true });
52
+ exports.isValidEventId = exports.generateEventId = exports.BatchSender = exports.SessionManager = exports.IndexedDBStorage = exports.InMemoryStorage = exports.OfflineQueue = exports.Apex = void 0;
53
+ const core_1 = require("@capacitor/core");
54
+ /**
55
+ * Capacitor plugin proxy. In a native app, calls route through the bridge to
56
+ * the iOS (Swift) or Android (Kotlin) implementation. In a web context
57
+ * (browser or Capacitor PWA), the web fallback in `./web.ts` takes over.
58
+ */
59
+ exports.Apex = (0, core_1.registerPlugin)("ApexCapacitorPlugin", {
60
+ web: () => Promise.resolve().then(() => __importStar(require("./web"))).then((m) => new m.ApexCapacitorWeb()),
61
+ });
62
+ // Re-export types so consumers can import them cleanly.
63
+ __exportStar(require("./definitions"), exports);
64
+ // Re-export core modules for advanced/test usage.
65
+ var offline_queue_1 = require("./offline-queue");
66
+ Object.defineProperty(exports, "OfflineQueue", { enumerable: true, get: function () { return offline_queue_1.OfflineQueue; } });
67
+ Object.defineProperty(exports, "InMemoryStorage", { enumerable: true, get: function () { return offline_queue_1.InMemoryStorage; } });
68
+ Object.defineProperty(exports, "IndexedDBStorage", { enumerable: true, get: function () { return offline_queue_1.IndexedDBStorage; } });
69
+ var session_manager_1 = require("./session-manager");
70
+ Object.defineProperty(exports, "SessionManager", { enumerable: true, get: function () { return session_manager_1.SessionManager; } });
71
+ var batch_sender_1 = require("./batch-sender");
72
+ Object.defineProperty(exports, "BatchSender", { enumerable: true, get: function () { return batch_sender_1.BatchSender; } });
73
+ var event_id_1 = require("./event-id");
74
+ Object.defineProperty(exports, "generateEventId", { enumerable: true, get: function () { return event_id_1.generateEventId; } });
75
+ Object.defineProperty(exports, "isValidEventId", { enumerable: true, get: function () { return event_id_1.isValidEventId; } });
76
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;GAYG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEH,0CAAiD;AAGjD;;;;GAIG;AACU,QAAA,IAAI,GAAwB,IAAA,qBAAc,EACrD,qBAAqB,EACrB;IACE,GAAG,EAAE,GAAG,EAAE,CAAC,kDAAO,OAAO,IAAE,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,gBAAgB,EAAE,CAAC;CACjE,CACF,CAAC;AAEF,wDAAwD;AACxD,gDAA8B;AAE9B,kDAAkD;AAClD,iDAAkF;AAAzE,6GAAA,YAAY,OAAA;AAAE,gHAAA,eAAe,OAAA;AAAE,iHAAA,gBAAgB,OAAA;AAExD,qDAAmD;AAA1C,iHAAA,cAAc,OAAA;AAEvB,+CAA6C;AAApC,2GAAA,WAAW,OAAA;AAEpB,uCAA6D;AAApD,2GAAA,eAAe,OAAA;AAAE,0GAAA,cAAc,OAAA"}