@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,79 +0,0 @@
1
- /**
2
- * The click an SDK resolve records: an app opening a link through the SDK is a
3
- * person's tap, whatever HTTP library the app sends it with.
4
- */
5
- import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
6
- import Fastify from 'fastify';
7
- const query = vi.fn();
8
- vi.mock('../lib/database.js', () => ({ db: { query: (...a) => query(...a) } }));
9
- import { sdkRoutes } from './sdk.js';
10
- const LINK_ID = '00000000-0000-0000-0000-0000000000aa';
11
- function mockDb() {
12
- query.mockReset();
13
- query.mockImplementation(async (sql) => {
14
- if (/information_schema\.columns/i.test(sql))
15
- return { rows: [{ x: 1 }], rowCount: 1 };
16
- if (/INSERT INTO click_events/i.test(sql))
17
- return { rows: [{ id: 'click-1' }], rowCount: 1 };
18
- if (/FROM links/i.test(sql)) {
19
- return {
20
- rows: [{
21
- id: LINK_ID,
22
- short_code: 'abc123',
23
- organization_id: '00000000-0000-0000-0000-0000000000bb',
24
- original_url: 'https://example.com/landing',
25
- is_active: true,
26
- warn_at: null,
27
- owner_suspended_at: null,
28
- expires_at: null,
29
- utm_parameters: null,
30
- }],
31
- rowCount: 1,
32
- };
33
- }
34
- return { rows: [], rowCount: 0 };
35
- });
36
- }
37
- /** The is_bot and bot_reason the resolve stored, once its async insert has run. */
38
- async function storedClick() {
39
- for (let i = 0; i < 20; i++) {
40
- const insert = query.mock.calls.find(([sql]) => /INSERT INTO click_events/i.test(sql));
41
- if (insert) {
42
- const params = insert[1];
43
- return { isBot: params[16], botReason: params[17] };
44
- }
45
- await new Promise((r) => setImmediate(r));
46
- }
47
- throw new Error('no click recorded');
48
- }
49
- let app;
50
- beforeEach(async () => {
51
- mockDb();
52
- app = Fastify();
53
- await app.register(sdkRoutes);
54
- await app.ready();
55
- });
56
- afterEach(async () => {
57
- await new Promise((r) => setImmediate(r));
58
- await app.close();
59
- });
60
- describe('SDK resolve click classification', () => {
61
- it('records an Android SDK resolve (okhttp user agent) as a human click', async () => {
62
- const res = await app.inject({
63
- method: 'GET',
64
- url: '/api/sdk/v1/resolve/abc123',
65
- headers: { 'user-agent': 'okhttp/4.12.0', 'x-linkforty-sdk': 'android/1.4.0' },
66
- });
67
- expect(res.statusCode).toBe(200);
68
- expect(await storedClick()).toEqual({ isBot: false, botReason: null });
69
- });
70
- it('still records an okhttp request without the SDK header as a bot', async () => {
71
- await app.inject({
72
- method: 'GET',
73
- url: '/api/sdk/v1/resolve/abc123',
74
- headers: { 'user-agent': 'okhttp/4.12.0' },
75
- });
76
- expect(await storedClick()).toEqual({ isBot: true, botReason: 'ua' });
77
- });
78
- });
79
- //# sourceMappingURL=sdk.resolve-click.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"sdk.resolve-click.test.js","sourceRoot":"","sources":["../../src/routes/sdk.resolve-click.test.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=sdk.resolve-scope.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"sdk.resolve-scope.test.d.ts","sourceRoot":"","sources":["../../src/routes/sdk.resolve-scope.test.ts"],"names":[],"mappings":""}
@@ -1,105 +0,0 @@
1
- /**
2
- * An SDK that names its app in X-LinkForty-App-Token only resolves that app's
3
- * organization's links.
4
- */
5
- import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
6
- import Fastify from 'fastify';
7
- const query = vi.fn();
8
- vi.mock('../lib/database.js', () => ({ db: { query: (...a) => query(...a) } }));
9
- import { sdkRoutes } from './sdk.js';
10
- const ORG_A = '00000000-0000-0000-0000-00000000000a';
11
- const ORG_B = '00000000-0000-0000-0000-00000000000b';
12
- const TOKEN_A = 'at_app_a';
13
- function link(organizationId) {
14
- return {
15
- id: '00000000-0000-0000-0000-0000000000aa',
16
- short_code: 'abc123',
17
- organization_id: organizationId,
18
- original_url: 'https://example.com/landing',
19
- is_active: true,
20
- warn_at: null,
21
- owner_suspended_at: null,
22
- expires_at: null,
23
- utm_parameters: null,
24
- };
25
- }
26
- /** The database holds one link with the code, owned by `owner`. */
27
- function mockDb(owner) {
28
- query.mockReset();
29
- query.mockImplementation(async (sql) => {
30
- if (/information_schema\.columns/i.test(sql))
31
- return { rows: [{ x: 1 }], rowCount: 1 };
32
- if (/INSERT INTO click_events/i.test(sql))
33
- return { rows: [{ id: 'click-1' }], rowCount: 1 };
34
- if (/FROM links/i.test(sql))
35
- return { rows: [link(owner)], rowCount: 1 };
36
- return { rows: [], rowCount: 0 };
37
- });
38
- }
39
- const resolveInstallScope = vi.fn(async (_request, body) => body.appToken === TOKEN_A ? { organizationId: ORG_A } : null);
40
- let app;
41
- async function build(redis) {
42
- app = Fastify();
43
- if (redis)
44
- app.decorate('redis', redis);
45
- await app.register(sdkRoutes, { resolveInstallScope });
46
- await app.ready();
47
- }
48
- const resolve = (headers = {}) => app.inject({ method: 'GET', url: '/api/sdk/v1/resolve/abc123', headers: { 'user-agent': 'okhttp/4.12.0', ...headers } });
49
- const clickRecorded = async () => {
50
- for (let i = 0; i < 10; i++)
51
- await new Promise((r) => setImmediate(r));
52
- return query.mock.calls.some(([sql]) => /INSERT INTO click_events/i.test(String(sql)));
53
- };
54
- beforeEach(() => {
55
- resolveInstallScope.mockClear();
56
- });
57
- afterEach(async () => {
58
- await new Promise((r) => setImmediate(r));
59
- await app.close();
60
- });
61
- describe('SDK resolve scoped to the app named in X-LinkForty-App-Token', () => {
62
- it("resolves the app's own organization's link", async () => {
63
- mockDb(ORG_A);
64
- await build();
65
- const res = await resolve({ 'x-linkforty-app-token': TOKEN_A });
66
- expect(res.statusCode).toBe(200);
67
- expect(await clickRecorded()).toBe(true);
68
- });
69
- it("answers another organization's code as unknown and records no click", async () => {
70
- mockDb(ORG_B);
71
- await build();
72
- const res = await resolve({ 'x-linkforty-app-token': TOKEN_A });
73
- expect(res.statusCode).toBe(404);
74
- expect(await clickRecorded()).toBe(false);
75
- });
76
- it("prefers the app's organization when looking a bare code up", async () => {
77
- mockDb(ORG_A);
78
- await build();
79
- await resolve({ 'x-linkforty-app-token': TOKEN_A });
80
- const lookup = query.mock.calls.find(([sql]) => /FROM links/i.test(String(sql)));
81
- expect(lookup?.[1]).toEqual(['abc123', ORG_A]);
82
- });
83
- it('resolves as before without the header', async () => {
84
- mockDb(ORG_B);
85
- await build();
86
- const res = await resolve();
87
- expect(res.statusCode).toBe(200);
88
- expect(resolveInstallScope).not.toHaveBeenCalled();
89
- });
90
- it('resolves as before for a token no organization has', async () => {
91
- mockDb(ORG_B);
92
- await build();
93
- const res = await resolve({ 'x-linkforty-app-token': 'at_unknown' });
94
- expect(res.statusCode).toBe(200);
95
- });
96
- it("refuses another organization's link read from the cache", async () => {
97
- mockDb(ORG_A);
98
- const cached = JSON.stringify(link(ORG_B));
99
- await build({ get: async () => cached, setex: async () => undefined });
100
- const res = await resolve({ 'x-linkforty-app-token': TOKEN_A });
101
- expect(res.statusCode).toBe(404);
102
- expect(await clickRecorded()).toBe(false);
103
- });
104
- });
105
- //# sourceMappingURL=sdk.resolve-scope.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"sdk.resolve-scope.test.js","sourceRoot":"","sources":["../../src/routes/sdk.resolve-scope.test.ts"],"names":[],"mappings":"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"}