@linkforty/core 1.44.1 → 1.44.2

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 (173) hide show
  1. package/package.json +2 -1
  2. package/dist/index.config.test.d.ts +0 -2
  3. package/dist/index.config.test.d.ts.map +0 -1
  4. package/dist/index.config.test.js +0 -87
  5. package/dist/index.config.test.js.map +0 -1
  6. package/dist/lib/bot-detection.test.d.ts +0 -2
  7. package/dist/lib/bot-detection.test.d.ts.map +0 -1
  8. package/dist/lib/bot-detection.test.js +0 -65
  9. package/dist/lib/bot-detection.test.js.map +0 -1
  10. package/dist/lib/client-ip.test.d.ts +0 -7
  11. package/dist/lib/client-ip.test.d.ts.map +0 -1
  12. package/dist/lib/client-ip.test.js +0 -114
  13. package/dist/lib/client-ip.test.js.map +0 -1
  14. package/dist/lib/config.test.d.ts +0 -2
  15. package/dist/lib/config.test.d.ts.map +0 -1
  16. package/dist/lib/config.test.js +0 -126
  17. package/dist/lib/config.test.js.map +0 -1
  18. package/dist/lib/database.test.d.ts +0 -2
  19. package/dist/lib/database.test.d.ts.map +0 -1
  20. package/dist/lib/database.test.js +0 -180
  21. package/dist/lib/database.test.js.map +0 -1
  22. package/dist/lib/deep-link-payload.test.d.ts +0 -2
  23. package/dist/lib/deep-link-payload.test.d.ts.map +0 -1
  24. package/dist/lib/deep-link-payload.test.js +0 -202
  25. package/dist/lib/deep-link-payload.test.js.map +0 -1
  26. package/dist/lib/event-emitter.test.d.ts +0 -2
  27. package/dist/lib/event-emitter.test.d.ts.map +0 -1
  28. package/dist/lib/event-emitter.test.js +0 -162
  29. package/dist/lib/event-emitter.test.js.map +0 -1
  30. package/dist/lib/fingerprint.test.d.ts +0 -2
  31. package/dist/lib/fingerprint.test.d.ts.map +0 -1
  32. package/dist/lib/fingerprint.test.js +0 -750
  33. package/dist/lib/fingerprint.test.js.map +0 -1
  34. package/dist/lib/launchpad.test.d.ts +0 -2
  35. package/dist/lib/launchpad.test.d.ts.map +0 -1
  36. package/dist/lib/launchpad.test.js +0 -368
  37. package/dist/lib/launchpad.test.js.map +0 -1
  38. package/dist/lib/link-lookup.test.d.ts +0 -2
  39. package/dist/lib/link-lookup.test.d.ts.map +0 -1
  40. package/dist/lib/link-lookup.test.js +0 -61
  41. package/dist/lib/link-lookup.test.js.map +0 -1
  42. package/dist/lib/link-resolution-cache.test.d.ts +0 -2
  43. package/dist/lib/link-resolution-cache.test.d.ts.map +0 -1
  44. package/dist/lib/link-resolution-cache.test.js +0 -45
  45. package/dist/lib/link-resolution-cache.test.js.map +0 -1
  46. package/dist/lib/link-safety.test.d.ts +0 -2
  47. package/dist/lib/link-safety.test.d.ts.map +0 -1
  48. package/dist/lib/link-safety.test.js +0 -211
  49. package/dist/lib/link-safety.test.js.map +0 -1
  50. package/dist/lib/not-found-page.test.d.ts +0 -2
  51. package/dist/lib/not-found-page.test.d.ts.map +0 -1
  52. package/dist/lib/not-found-page.test.js +0 -151
  53. package/dist/lib/not-found-page.test.js.map +0 -1
  54. package/dist/lib/portable/cli.test.d.ts +0 -2
  55. package/dist/lib/portable/cli.test.d.ts.map +0 -1
  56. package/dist/lib/portable/cli.test.js +0 -98
  57. package/dist/lib/portable/cli.test.js.map +0 -1
  58. package/dist/lib/portable/portable.integration.test.d.ts +0 -2
  59. package/dist/lib/portable/portable.integration.test.d.ts.map +0 -1
  60. package/dist/lib/portable/portable.integration.test.js +0 -139
  61. package/dist/lib/portable/portable.integration.test.js.map +0 -1
  62. package/dist/lib/portable/registry.schema.test.d.ts +0 -2
  63. package/dist/lib/portable/registry.schema.test.d.ts.map +0 -1
  64. package/dist/lib/portable/registry.schema.test.js +0 -59
  65. package/dist/lib/portable/registry.schema.test.js.map +0 -1
  66. package/dist/lib/scanner-detection.test.d.ts +0 -2
  67. package/dist/lib/scanner-detection.test.d.ts.map +0 -1
  68. package/dist/lib/scanner-detection.test.js +0 -124
  69. package/dist/lib/scanner-detection.test.js.map +0 -1
  70. package/dist/lib/schema-guard.test.d.ts +0 -2
  71. package/dist/lib/schema-guard.test.d.ts.map +0 -1
  72. package/dist/lib/schema-guard.test.js +0 -83
  73. package/dist/lib/schema-guard.test.js.map +0 -1
  74. package/dist/lib/utils.test.d.ts +0 -2
  75. package/dist/lib/utils.test.d.ts.map +0 -1
  76. package/dist/lib/utils.test.js +0 -261
  77. package/dist/lib/utils.test.js.map +0 -1
  78. package/dist/lib/webhook.test.d.ts +0 -2
  79. package/dist/lib/webhook.test.d.ts.map +0 -1
  80. package/dist/lib/webhook.test.js +0 -340
  81. package/dist/lib/webhook.test.js.map +0 -1
  82. package/dist/routes/health.test.d.ts +0 -2
  83. package/dist/routes/health.test.d.ts.map +0 -1
  84. package/dist/routes/health.test.js +0 -82
  85. package/dist/routes/health.test.js.map +0 -1
  86. package/dist/routes/preview.test.d.ts +0 -2
  87. package/dist/routes/preview.test.d.ts.map +0 -1
  88. package/dist/routes/preview.test.js +0 -111
  89. package/dist/routes/preview.test.js.map +0 -1
  90. package/dist/routes/qr.test.d.ts +0 -2
  91. package/dist/routes/qr.test.d.ts.map +0 -1
  92. package/dist/routes/qr.test.js +0 -67
  93. package/dist/routes/qr.test.js.map +0 -1
  94. package/dist/routes/redirect.click-event.test.d.ts +0 -2
  95. package/dist/routes/redirect.click-event.test.d.ts.map +0 -1
  96. package/dist/routes/redirect.click-event.test.js +0 -85
  97. package/dist/routes/redirect.click-event.test.js.map +0 -1
  98. package/dist/routes/redirect.host-scope.integration.test.d.ts +0 -2
  99. package/dist/routes/redirect.host-scope.integration.test.d.ts.map +0 -1
  100. package/dist/routes/redirect.host-scope.integration.test.js +0 -105
  101. package/dist/routes/redirect.host-scope.integration.test.js.map +0 -1
  102. package/dist/routes/redirect.interstitial.test.d.ts +0 -2
  103. package/dist/routes/redirect.interstitial.test.d.ts.map +0 -1
  104. package/dist/routes/redirect.interstitial.test.js +0 -128
  105. package/dist/routes/redirect.interstitial.test.js.map +0 -1
  106. package/dist/routes/redirect.launchpad.test.d.ts +0 -2
  107. package/dist/routes/redirect.launchpad.test.d.ts.map +0 -1
  108. package/dist/routes/redirect.launchpad.test.js +0 -515
  109. package/dist/routes/redirect.launchpad.test.js.map +0 -1
  110. package/dist/routes/redirect.no-web-destination.test.d.ts +0 -2
  111. package/dist/routes/redirect.no-web-destination.test.d.ts.map +0 -1
  112. package/dist/routes/redirect.no-web-destination.test.js +0 -176
  113. package/dist/routes/redirect.no-web-destination.test.js.map +0 -1
  114. package/dist/routes/redirect.not-found.test.d.ts +0 -2
  115. package/dist/routes/redirect.not-found.test.d.ts.map +0 -1
  116. package/dist/routes/redirect.not-found.test.js +0 -280
  117. package/dist/routes/redirect.not-found.test.js.map +0 -1
  118. package/dist/routes/redirect.safety.test.d.ts +0 -2
  119. package/dist/routes/redirect.safety.test.d.ts.map +0 -1
  120. package/dist/routes/redirect.safety.test.js +0 -284
  121. package/dist/routes/redirect.safety.test.js.map +0 -1
  122. package/dist/routes/redirect.store-url.test.d.ts +0 -2
  123. package/dist/routes/redirect.store-url.test.d.ts.map +0 -1
  124. package/dist/routes/redirect.store-url.test.js +0 -239
  125. package/dist/routes/redirect.store-url.test.js.map +0 -1
  126. package/dist/routes/redirect.test.d.ts +0 -2
  127. package/dist/routes/redirect.test.d.ts.map +0 -1
  128. package/dist/routes/redirect.test.js +0 -158
  129. package/dist/routes/redirect.test.js.map +0 -1
  130. package/dist/routes/redirect.web-link.test.d.ts +0 -2
  131. package/dist/routes/redirect.web-link.test.d.ts.map +0 -1
  132. package/dist/routes/redirect.web-link.test.js +0 -138
  133. package/dist/routes/redirect.web-link.test.js.map +0 -1
  134. package/dist/routes/sdk-cache-bypass.test.d.ts +0 -2
  135. package/dist/routes/sdk-cache-bypass.test.d.ts.map +0 -1
  136. package/dist/routes/sdk-cache-bypass.test.js +0 -175
  137. package/dist/routes/sdk-cache-bypass.test.js.map +0 -1
  138. package/dist/routes/sdk.device-values.integration.test.d.ts +0 -2
  139. package/dist/routes/sdk.device-values.integration.test.d.ts.map +0 -1
  140. package/dist/routes/sdk.device-values.integration.test.js +0 -132
  141. package/dist/routes/sdk.device-values.integration.test.js.map +0 -1
  142. package/dist/routes/sdk.event.test.d.ts +0 -2
  143. package/dist/routes/sdk.event.test.d.ts.map +0 -1
  144. package/dist/routes/sdk.event.test.js +0 -284
  145. package/dist/routes/sdk.event.test.js.map +0 -1
  146. package/dist/routes/sdk.install-certainty.integration.test.d.ts +0 -2
  147. package/dist/routes/sdk.install-certainty.integration.test.d.ts.map +0 -1
  148. package/dist/routes/sdk.install-certainty.integration.test.js +0 -104
  149. package/dist/routes/sdk.install-certainty.integration.test.js.map +0 -1
  150. package/dist/routes/sdk.install-live-links.integration.test.d.ts +0 -2
  151. package/dist/routes/sdk.install-live-links.integration.test.d.ts.map +0 -1
  152. package/dist/routes/sdk.install-live-links.integration.test.js +0 -92
  153. package/dist/routes/sdk.install-live-links.integration.test.js.map +0 -1
  154. package/dist/routes/sdk.install-referrer.integration.test.d.ts +0 -2
  155. package/dist/routes/sdk.install-referrer.integration.test.d.ts.map +0 -1
  156. package/dist/routes/sdk.install-referrer.integration.test.js +0 -187
  157. package/dist/routes/sdk.install-referrer.integration.test.js.map +0 -1
  158. package/dist/routes/sdk.install-window-once.integration.test.d.ts +0 -2
  159. package/dist/routes/sdk.install-window-once.integration.test.d.ts.map +0 -1
  160. package/dist/routes/sdk.install-window-once.integration.test.js +0 -147
  161. package/dist/routes/sdk.install-window-once.integration.test.js.map +0 -1
  162. package/dist/routes/sdk.install.test.d.ts +0 -2
  163. package/dist/routes/sdk.install.test.d.ts.map +0 -1
  164. package/dist/routes/sdk.install.test.js +0 -99
  165. package/dist/routes/sdk.install.test.js.map +0 -1
  166. package/dist/routes/sdk.resolve-click.test.d.ts +0 -2
  167. package/dist/routes/sdk.resolve-click.test.d.ts.map +0 -1
  168. package/dist/routes/sdk.resolve-click.test.js +0 -79
  169. package/dist/routes/sdk.resolve-click.test.js.map +0 -1
  170. package/dist/routes/sdk.resolve-scope.test.d.ts +0 -2
  171. package/dist/routes/sdk.resolve-scope.test.d.ts.map +0 -1
  172. package/dist/routes/sdk.resolve-scope.test.js +0 -105
  173. package/dist/routes/sdk.resolve-scope.test.js.map +0 -1
@@ -1,180 +0,0 @@
1
- import pg from 'pg';
2
- import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest';
3
- import { SCHEMA_INIT_LOCK_KEY, db, initializeDatabase } from './database.js';
4
- /**
5
- * Schema initialisation must serialise across processes.
6
- *
7
- * `CREATE TABLE IF NOT EXISTS` is not atomic — the existence check and the
8
- * creation are separate steps — so two connections initialising an empty
9
- * database at once can both find a table absent and both try to create it. The
10
- * loser fails with a `pg_type_typname_nsp_index` unique violation. An advisory
11
- * lock makes the second caller wait instead.
12
- *
13
- * This needs a real database: the behaviour under test is a property of
14
- * Postgres locking, and a mocked client would accept any sequence of queries.
15
- * The suite skips itself when DATABASE_URL is absent so `npm test` stays green
16
- * without one.
17
- */
18
- const ADMIN_URL = process.env.DATABASE_URL;
19
- if (!ADMIN_URL) {
20
- // eslint-disable-next-line no-console
21
- console.warn('\n database.test.ts skipped: set DATABASE_URL to run it.' +
22
- '\n It creates and drops a scratch database, so the user needs CREATEDB.\n');
23
- }
24
- describe.skipIf(!ADMIN_URL)('initializeDatabase schema lock', () => {
25
- // A scratch database per run: the race only exists against an EMPTY schema,
26
- // and initialising a shared database would also mutate whatever is in it.
27
- const scratchName = `lf_core_schema_init_${Date.now()}`;
28
- let admin;
29
- let scratchUrl;
30
- beforeAll(async () => {
31
- admin = new pg.Client({ connectionString: ADMIN_URL });
32
- await admin.connect();
33
- await admin.query(`CREATE DATABASE ${scratchName}`);
34
- const url = new URL(ADMIN_URL);
35
- url.pathname = `/${scratchName}`;
36
- scratchUrl = url.toString();
37
- }, 30000);
38
- afterAll(async () => {
39
- // The pool `initializeDatabase` created still holds connections, and
40
- // Postgres refuses to drop a database that has any.
41
- await db?.end().catch(() => undefined);
42
- await admin.query(`DROP DATABASE IF EXISTS ${scratchName} WITH (FORCE)`);
43
- await admin.end();
44
- }, 30000);
45
- it('waits for a concurrent initialisation rather than racing it', async () => {
46
- // Stand in for a second instance that got there first.
47
- const holder = new pg.Client({ connectionString: scratchUrl });
48
- await holder.connect();
49
- await holder.query('SELECT pg_advisory_lock($1)', [SCHEMA_INIT_LOCK_KEY]);
50
- let settled = false;
51
- const init = initializeDatabase({ url: scratchUrl, pool: { min: 1, max: 2 } }).then(() => {
52
- settled = true;
53
- });
54
- // Long enough that an unsynchronised initialisation would have finished
55
- // creating tables and resolved.
56
- await new Promise((resolve) => setTimeout(resolve, 500));
57
- expect(settled).toBe(false);
58
- await holder.query('SELECT pg_advisory_unlock($1)', [SCHEMA_INIT_LOCK_KEY]);
59
- await holder.end();
60
- await init;
61
- expect(settled).toBe(true);
62
- }, 60000);
63
- it('releases the lock once initialisation completes', async () => {
64
- // Runs after the case above, which left a fully initialised database. A
65
- // leaked lock would block every subsequent boot, so assert it is gone.
66
- const probe = new pg.Client({ connectionString: scratchUrl });
67
- await probe.connect();
68
- try {
69
- const { rows } = await probe.query('SELECT pg_try_advisory_lock($1) AS acquired', [
70
- SCHEMA_INIT_LOCK_KEY,
71
- ]);
72
- expect(rows[0].acquired).toBe(true);
73
- await probe.query('SELECT pg_advisory_unlock($1)', [SCHEMA_INIT_LOCK_KEY]);
74
- }
75
- finally {
76
- await probe.end();
77
- }
78
- }, 30000);
79
- });
80
- describe.skipIf(!ADMIN_URL)('initialisation against a table someone is reading', () => {
81
- // Postgres takes a table's lock before it evaluates IF NOT EXISTS, so a
82
- // second start used to park an ACCESS EXCLUSIVE request on `links` behind
83
- // any long reader — and every redirect behind that. With the catalog guard
84
- // nothing is sent for a column that exists, and with a lock timeout a
85
- // statement that does need the table gives up instead of queueing it.
86
- const scratchName = `lf_core_schema_guard_${Date.now()}`;
87
- let admin;
88
- let scratchUrl;
89
- const pools = [];
90
- beforeAll(async () => {
91
- admin = new pg.Client({ connectionString: ADMIN_URL });
92
- await admin.connect();
93
- await admin.query(`CREATE DATABASE ${scratchName}`);
94
- const url = new URL(ADMIN_URL);
95
- url.pathname = `/${scratchName}`;
96
- scratchUrl = url.toString();
97
- // First start: every table, column and index exists afterwards.
98
- await initializeDatabase({ url: scratchUrl, pool: { min: 1, max: 2 } });
99
- pools.push(db);
100
- }, 60000);
101
- afterAll(async () => {
102
- for (const p of pools)
103
- await p.end().catch(() => undefined);
104
- await db?.end().catch(() => undefined);
105
- await admin.query(`DROP DATABASE IF EXISTS ${scratchName} WITH (FORCE)`);
106
- await admin.end();
107
- }, 30000);
108
- it('a second start completes while a transaction holds ACCESS SHARE on links, and the setting does not leak', async () => {
109
- const reader = new pg.Client({ connectionString: scratchUrl });
110
- await reader.connect();
111
- try {
112
- await reader.query('BEGIN');
113
- await reader.query('SELECT 1 FROM links LIMIT 1');
114
- const started = Date.now();
115
- await initializeDatabase({ url: scratchUrl, pool: { min: 1, max: 2 }, lockTimeoutMs: 2000 });
116
- pools.push(db);
117
- // Nothing waited: well under a single lock timeout.
118
- expect(Date.now() - started).toBeLessThan(10000);
119
- // The reader was never blocked either.
120
- const t = Date.now();
121
- await reader.query('SELECT 1 FROM links LIMIT 1');
122
- expect(Date.now() - t).toBeLessThan(1000);
123
- // The timeout was session-level on the initialisation client and was
124
- // reset before that client went back to the pool.
125
- const { rows } = await db.query('SHOW lock_timeout');
126
- expect(rows[0].lock_timeout).toBe('0');
127
- }
128
- finally {
129
- await reader.query('ROLLBACK').catch(() => undefined);
130
- await reader.end();
131
- }
132
- }, 60000);
133
- it('a statement that does need the table fails with 55P03 after the timeout instead of queueing it', async () => {
134
- const reader = new pg.Client({ connectionString: scratchUrl });
135
- const other = new pg.Client({ connectionString: scratchUrl });
136
- await reader.connect();
137
- await other.connect();
138
- try {
139
- await reader.query('BEGIN');
140
- await reader.query('SELECT 1 FROM links LIMIT 1');
141
- await other.query('SET lock_timeout = 1000');
142
- const t = Date.now();
143
- await expect(other.query('ALTER TABLE links ADD COLUMN probe_column_not_guarded INTEGER')).rejects.toMatchObject({ code: '55P03' });
144
- expect(Date.now() - t).toBeLessThan(5000);
145
- }
146
- finally {
147
- await reader.query('ROLLBACK').catch(() => undefined);
148
- await reader.end();
149
- await other.end();
150
- }
151
- }, 30000);
152
- });
153
- describe.skipIf(!ADMIN_URL)('idle connection errors', () => {
154
- const scratchName = `lf_core_idle_error_${Date.now()}`;
155
- let admin;
156
- beforeAll(async () => {
157
- admin = new pg.Client({ connectionString: ADMIN_URL });
158
- await admin.connect();
159
- await admin.query(`CREATE DATABASE ${scratchName}`);
160
- }, 30000);
161
- afterAll(async () => {
162
- await db?.end().catch(() => undefined);
163
- await admin.query(`DROP DATABASE IF EXISTS ${scratchName} WITH (FORCE)`);
164
- await admin.end();
165
- }, 30000);
166
- it('keeps the process alive when the server closes an idle connection, and serves the next query', async () => {
167
- const url = new URL(ADMIN_URL);
168
- url.pathname = `/${scratchName}`;
169
- await initializeDatabase({ url: url.toString(), pool: { min: 1, max: 2 } });
170
- await db.query('SELECT 1');
171
- expect(db.idleCount).toBeGreaterThan(0);
172
- // No listener of the test's own: an unhandled pool error here would fail
173
- // the run (and exit a server).
174
- await admin.query(`SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = $1 AND pid <> pg_backend_pid()`, [scratchName]);
175
- // The pool drops each closed connection once it has reported the error.
176
- await vi.waitFor(() => expect(db.totalCount).toBe(0), { timeout: 10000 });
177
- expect((await db.query('SELECT 1 AS ok')).rows[0].ok).toBe(1);
178
- }, 60000);
179
- });
180
- //# sourceMappingURL=database.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"database.test.js","sourceRoot":"","sources":["../../src/lib/database.test.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=deep-link-payload.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"deep-link-payload.test.d.ts","sourceRoot":"","sources":["../../src/lib/deep-link-payload.test.ts"],"names":[],"mappings":""}
@@ -1,202 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import { toDeepLinkPayload, CANONICAL_DEEP_LINK_KEYS, } from './deep-link-payload.js';
3
- const link = {
4
- id: 'link-123',
5
- short_code: 'abc123',
6
- original_url: 'https://example.com/product/456',
7
- deep_link_path: '/product/456',
8
- app_scheme: 'myapp',
9
- ios_app_store_url: 'https://apps.apple.com/app/id123',
10
- android_app_store_url: 'https://play.google.com/store/apps/details?id=com.example',
11
- web_fallback_url: 'https://example.com',
12
- utm_parameters: { source: 'facebook', campaign: 'summer' },
13
- targeting_rules: { countries: ['US'] },
14
- deep_link_parameters: { productId: '456' },
15
- };
16
- const clickedAt = new Date('2026-01-15T10:30:00.000Z');
17
- /** How the install endpoint projects a matched link. */
18
- function installPayload(row = link) {
19
- return toDeepLinkPayload(row, {
20
- clickedAt,
21
- isDeferred: true,
22
- confidenceScore: 85,
23
- matchedFactors: ['userAgent', 'timezone'],
24
- attributionMethod: 'fingerprint',
25
- competingLinks: 0,
26
- legacyInstallKeys: true,
27
- });
28
- }
29
- /** How the resolve endpoint projects a directly opened link. */
30
- function resolvePayload(row = link) {
31
- return toDeepLinkPayload(row, {
32
- clickedAt: clickedAt.toISOString(),
33
- isDeferred: false,
34
- });
35
- }
36
- describe('toDeepLinkPayload', () => {
37
- it('projects a link into the shape the SDK DeepLinkData model expects', () => {
38
- expect(resolvePayload()).toEqual({
39
- shortCode: 'abc123',
40
- linkId: 'link-123',
41
- deepLinkPath: '/product/456',
42
- appScheme: 'myapp',
43
- iosUrl: 'https://apps.apple.com/app/id123',
44
- androidUrl: 'https://play.google.com/store/apps/details?id=com.example',
45
- webUrl: 'https://example.com',
46
- utmParameters: { source: 'facebook', campaign: 'summer' },
47
- customParameters: { productId: '456' },
48
- clickedAt: '2026-01-15T10:30:00.000Z',
49
- isDeferred: false,
50
- });
51
- });
52
- it('normalizes a Date clickedAt to an ISO string', () => {
53
- expect(installPayload().clickedAt).toBe('2026-01-15T10:30:00.000Z');
54
- });
55
- it('omits empty canonical fields rather than sending null', () => {
56
- const payload = resolvePayload({ short_code: 'bare' });
57
- expect(payload.shortCode).toBe('bare');
58
- expect('deepLinkPath' in payload).toBe(false);
59
- expect('appScheme' in payload).toBe(false);
60
- expect('webUrl' in payload).toBe(false);
61
- expect('linkId' in payload).toBe(false);
62
- });
63
- it('carries attribution metadata on deferred opens only', () => {
64
- const deferred = installPayload();
65
- expect(deferred.isDeferred).toBe(true);
66
- expect(deferred.confidenceScore).toBe(85);
67
- expect(deferred.matchedFactors).toEqual(['userAgent', 'timezone']);
68
- expect(deferred.attributionMethod).toBe('fingerprint');
69
- // Zero is reported, not dropped: it is the answer an app checks for.
70
- expect(deferred.competingLinks).toBe(0);
71
- const direct = resolvePayload();
72
- expect(direct.isDeferred).toBe(false);
73
- expect('confidenceScore' in direct).toBe(false);
74
- expect('matchedFactors' in direct).toBe(false);
75
- expect('attributionMethod' in direct).toBe(false);
76
- expect('competingLinks' in direct).toBe(false);
77
- });
78
- it('reports a zero confidence score rather than dropping it', () => {
79
- const payload = toDeepLinkPayload(link, {
80
- clickedAt,
81
- isDeferred: true,
82
- confidenceScore: 0,
83
- matchedFactors: [],
84
- });
85
- expect(payload.confidenceScore).toBe(0);
86
- expect(payload.matchedFactors).toEqual([]);
87
- });
88
- });
89
- /**
90
- * The contract that keeps the install and resolve payloads from drifting apart
91
- * again. Both endpoints describe the same link to the same SDK model, so every
92
- * canonical field must carry the same value on both paths.
93
- */
94
- describe('install and resolve payload contract', () => {
95
- it('agrees field for field on every canonical key', () => {
96
- const install = installPayload();
97
- const resolve = resolvePayload();
98
- for (const key of CANONICAL_DEEP_LINK_KEYS) {
99
- if (key === 'isDeferred')
100
- continue; // The one field that must differ.
101
- expect(resolve[key], `resolve.${key}`).toEqual(install[key]);
102
- }
103
- });
104
- it('gives the deferred payload every field an app needs to route', () => {
105
- const payload = installPayload();
106
- // The whole point of a deferred deep link: a newly installed user lands on
107
- // the right screen, and the first session is credited to the link.
108
- expect(payload.deepLinkPath).toBe('/product/456');
109
- expect(payload.appScheme).toBe('myapp');
110
- expect(payload.customParameters).toEqual({ productId: '456' });
111
- expect(payload.linkId).toBe('link-123');
112
- });
113
- });
114
- /**
115
- * Every SDK already in the field reads the pre-1.22 install keys. App updates
116
- * take weeks to roll out, so these must keep their exact previous values —
117
- * including nulls, which is why they are asserted with `toBe`/`in` rather than
118
- * a loose truthiness check.
119
- */
120
- describe('legacy install keys', () => {
121
- it('emits the old aliases alongside the canonical ones', () => {
122
- const payload = installPayload();
123
- expect(payload.originalUrl).toBe('https://example.com/product/456');
124
- expect(payload.webFallbackUrl).toBe('https://example.com');
125
- expect(payload.targetingRules).toEqual({ countries: ['US'] });
126
- expect(payload.deepLinkParameters).toEqual({ productId: '456' });
127
- // The canonical spellings of the same values ship in the same payload.
128
- expect(payload.webUrl).toBe(payload.webFallbackUrl);
129
- expect(payload.customParameters).toEqual(payload.deepLinkParameters);
130
- });
131
- it('keeps null legacy values present rather than omitting the key', () => {
132
- const payload = installPayload({ short_code: 'bare' });
133
- expect(payload.originalUrl).toBeNull();
134
- expect(payload.webFallbackUrl).toBeNull();
135
- expect(payload.targetingRules).toBeNull();
136
- expect(payload.deepLinkParameters).toBeNull();
137
- });
138
- it('does not leak legacy keys into the resolve payload', () => {
139
- const payload = resolvePayload();
140
- expect('originalUrl' in payload).toBe(false);
141
- expect('webFallbackUrl' in payload).toBe(false);
142
- expect('targetingRules' in payload).toBe(false);
143
- expect('deepLinkParameters' in payload).toBe(false);
144
- });
145
- });
146
- describe('toDeepLinkPayload — click params', () => {
147
- const link = { short_code: 'abc123' };
148
- const base = { clickedAt: '2026-09-09T00:00:00.000Z', isDeferred: true };
149
- it('merges click params when the link has none configured', () => {
150
- const p = toDeepLinkPayload(link, { ...base, linkParams: { slug: 'titanic' } });
151
- expect(p.customParameters).toEqual({ slug: 'titanic' });
152
- });
153
- it('lets a click param override a configured one of the same name', () => {
154
- const p = toDeepLinkPayload({ ...link, deep_link_parameters: { slug: 'default', keep: 'me' } }, { ...base, linkParams: { slug: 'titanic' } });
155
- expect(p.customParameters).toEqual({ slug: 'titanic', keep: 'me' });
156
- });
157
- it('leaves the payload untouched when there are no click params', () => {
158
- const withParams = toDeepLinkPayload({ ...link, deep_link_parameters: { a: '1' } }, base);
159
- expect(withParams.customParameters).toEqual({ a: '1' });
160
- const withNone = toDeepLinkPayload(link, base);
161
- expect(withNone.customParameters).toBeUndefined();
162
- });
163
- it('treats an empty click-param object as no params', () => {
164
- const p = toDeepLinkPayload({ ...link, deep_link_parameters: { a: '1' } }, {
165
- ...base,
166
- linkParams: {},
167
- });
168
- expect(p.customParameters).toEqual({ a: '1' });
169
- });
170
- it('gives the legacy alias the same merged value as the canonical field', () => {
171
- const p = toDeepLinkPayload({ ...link, deep_link_parameters: { slug: 'default' } }, { ...base, linkParams: { slug: 'titanic' }, legacyInstallKeys: true });
172
- // SDKs in the field read deepLinkParameters in preference to
173
- // customParameters, so the two disagreeing would make the merge invisible.
174
- expect(p.deepLinkParameters).toEqual(p.customParameters);
175
- expect(p.deepLinkParameters).toEqual({ slug: 'titanic' });
176
- });
177
- it('keeps the legacy alias null when nothing is configured or carried', () => {
178
- const p = toDeepLinkPayload(link, { ...base, legacyInstallKeys: true });
179
- expect(p.deepLinkParameters).toBeNull();
180
- });
181
- it('does not throw when deep_link_parameters is null, a scalar or an array', () => {
182
- for (const bad of [null, 'nope', 42, ['a', 'b']]) {
183
- const p = toDeepLinkPayload({ ...link, deep_link_parameters: bad }, {
184
- ...base,
185
- linkParams: { slug: 'titanic' },
186
- });
187
- expect(p.customParameters).toEqual({ slug: 'titanic' });
188
- }
189
- });
190
- it('introduces no key outside the canonical set', () => {
191
- // The merge must land inside customParameters, never as a new top-level
192
- // field — SDKs decode a fixed shape.
193
- const p = toDeepLinkPayload(link, { ...base, linkParams: { slug: 'titanic' } });
194
- const allowed = new Set([
195
- ...CANONICAL_DEEP_LINK_KEYS,
196
- 'confidenceScore',
197
- 'matchedFactors',
198
- ]);
199
- expect(Object.keys(p).filter((k) => !allowed.has(k))).toEqual([]);
200
- });
201
- });
202
- //# sourceMappingURL=deep-link-payload.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"deep-link-payload.test.js","sourceRoot":"","sources":["../../src/lib/deep-link-payload.test.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=event-emitter.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"event-emitter.test.d.ts","sourceRoot":"","sources":["../../src/lib/event-emitter.test.ts"],"names":[],"mappings":""}
@@ -1,162 +0,0 @@
1
- import { describe, it, expect, vi, beforeEach } from 'vitest';
2
- import { clickEventEmitter, emitClickEvent, subscribeToClickEvents, } from './event-emitter';
3
- const mockClickEvent = {
4
- eventId: 'evt-123',
5
- timestamp: '2026-03-10T00:00:00.000Z',
6
- linkId: 'link-abc',
7
- shortCode: 'abc123',
8
- userId: 'user-1',
9
- organizationId: 'org-1',
10
- ipAddress: '1.2.3.4',
11
- userAgent: 'Mozilla/5.0',
12
- country: 'US',
13
- city: 'New York',
14
- deviceType: 'web',
15
- platform: 'Windows',
16
- browser: 'Chrome',
17
- redirectUrl: 'https://example.com',
18
- redirectReason: 'web_fallback',
19
- targetingMatched: true,
20
- utmParameters: {
21
- source: 'newsletter',
22
- medium: 'email',
23
- campaign: 'spring',
24
- },
25
- referer: 'https://google.com',
26
- language: 'en-US',
27
- };
28
- describe('clickEventEmitter', () => {
29
- it('should be an EventEmitter instance', () => {
30
- expect(clickEventEmitter).toBeDefined();
31
- expect(typeof clickEventEmitter.on).toBe('function');
32
- expect(typeof clickEventEmitter.emit).toBe('function');
33
- expect(typeof clickEventEmitter.off).toBe('function');
34
- });
35
- });
36
- describe('emitClickEvent', () => {
37
- beforeEach(() => {
38
- clickEventEmitter.removeAllListeners('click');
39
- });
40
- it('should emit a click event with the provided data', () => {
41
- const handler = vi.fn();
42
- clickEventEmitter.on('click', handler);
43
- emitClickEvent(mockClickEvent);
44
- expect(handler).toHaveBeenCalledOnce();
45
- expect(handler).toHaveBeenCalledWith(mockClickEvent);
46
- });
47
- it('should emit to all registered listeners', () => {
48
- const handler1 = vi.fn();
49
- const handler2 = vi.fn();
50
- clickEventEmitter.on('click', handler1);
51
- clickEventEmitter.on('click', handler2);
52
- emitClickEvent(mockClickEvent);
53
- expect(handler1).toHaveBeenCalledOnce();
54
- expect(handler2).toHaveBeenCalledOnce();
55
- });
56
- it('should emit multiple times when called multiple times', () => {
57
- const handler = vi.fn();
58
- clickEventEmitter.on('click', handler);
59
- emitClickEvent(mockClickEvent);
60
- emitClickEvent({ ...mockClickEvent, eventId: 'evt-456' });
61
- expect(handler).toHaveBeenCalledTimes(2);
62
- });
63
- it('should pass the exact event data to the handler', () => {
64
- const handler = vi.fn();
65
- clickEventEmitter.on('click', handler);
66
- const eventData = {
67
- ...mockClickEvent,
68
- deviceType: 'ios',
69
- country: 'CA',
70
- targetingMatched: false,
71
- };
72
- emitClickEvent(eventData);
73
- expect(handler).toHaveBeenCalledWith(eventData);
74
- });
75
- it('should work with minimal required fields', () => {
76
- const handler = vi.fn();
77
- clickEventEmitter.on('click', handler);
78
- const minimalEvent = {
79
- eventId: 'evt-min',
80
- timestamp: '2026-03-10T00:00:00.000Z',
81
- linkId: 'link-min',
82
- shortCode: 'min',
83
- ipAddress: '0.0.0.0',
84
- userAgent: '',
85
- deviceType: 'web',
86
- redirectUrl: 'https://example.com',
87
- redirectReason: 'default',
88
- targetingMatched: true,
89
- };
90
- emitClickEvent(minimalEvent);
91
- expect(handler).toHaveBeenCalledWith(minimalEvent);
92
- });
93
- });
94
- describe('subscribeToClickEvents', () => {
95
- beforeEach(() => {
96
- clickEventEmitter.removeAllListeners('click');
97
- });
98
- it('should call the callback when a click event is emitted', () => {
99
- const callback = vi.fn();
100
- subscribeToClickEvents(callback);
101
- emitClickEvent(mockClickEvent);
102
- expect(callback).toHaveBeenCalledOnce();
103
- expect(callback).toHaveBeenCalledWith(mockClickEvent);
104
- });
105
- it('should return an unsubscribe function', () => {
106
- const callback = vi.fn();
107
- const unsubscribe = subscribeToClickEvents(callback);
108
- expect(typeof unsubscribe).toBe('function');
109
- });
110
- it('should stop receiving events after unsubscribing', () => {
111
- const callback = vi.fn();
112
- const unsubscribe = subscribeToClickEvents(callback);
113
- emitClickEvent(mockClickEvent);
114
- expect(callback).toHaveBeenCalledOnce();
115
- unsubscribe();
116
- emitClickEvent(mockClickEvent);
117
- expect(callback).toHaveBeenCalledOnce(); // still only once
118
- });
119
- it('should allow multiple subscribers independently', () => {
120
- const callback1 = vi.fn();
121
- const callback2 = vi.fn();
122
- const unsubscribe1 = subscribeToClickEvents(callback1);
123
- subscribeToClickEvents(callback2);
124
- emitClickEvent(mockClickEvent);
125
- expect(callback1).toHaveBeenCalledOnce();
126
- expect(callback2).toHaveBeenCalledOnce();
127
- unsubscribe1();
128
- emitClickEvent(mockClickEvent);
129
- expect(callback1).toHaveBeenCalledOnce(); // no new calls
130
- expect(callback2).toHaveBeenCalledTimes(2);
131
- });
132
- it('should not affect other subscribers when one unsubscribes', () => {
133
- const callback1 = vi.fn();
134
- const callback2 = vi.fn();
135
- const unsubscribe1 = subscribeToClickEvents(callback1);
136
- subscribeToClickEvents(callback2);
137
- unsubscribe1();
138
- emitClickEvent(mockClickEvent);
139
- expect(callback1).not.toHaveBeenCalled();
140
- expect(callback2).toHaveBeenCalledOnce();
141
- });
142
- it('should handle unsubscribe called multiple times without error', () => {
143
- const callback = vi.fn();
144
- const unsubscribe = subscribeToClickEvents(callback);
145
- expect(() => {
146
- unsubscribe();
147
- unsubscribe();
148
- }).not.toThrow();
149
- });
150
- it('should pass event data correctly to callback', () => {
151
- const received = [];
152
- subscribeToClickEvents((data) => received.push(data));
153
- const event1 = { ...mockClickEvent, eventId: 'e1', deviceType: 'ios' };
154
- const event2 = { ...mockClickEvent, eventId: 'e2', deviceType: 'android' };
155
- emitClickEvent(event1);
156
- emitClickEvent(event2);
157
- expect(received).toHaveLength(2);
158
- expect(received[0]).toEqual(event1);
159
- expect(received[1]).toEqual(event2);
160
- });
161
- });
162
- //# sourceMappingURL=event-emitter.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"event-emitter.test.js","sourceRoot":"","sources":["../../src/lib/event-emitter.test.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=fingerprint.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"fingerprint.test.d.ts","sourceRoot":"","sources":["../../src/lib/fingerprint.test.ts"],"names":[],"mappings":""}