@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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@linkforty/core",
3
- "version": "1.44.1",
3
+ "version": "1.44.2",
4
4
  "type": "module",
5
5
  "description": "Open-source deeplink management engine with device detection and analytics",
6
6
  "main": "dist/index.js",
@@ -91,6 +91,7 @@
91
91
  },
92
92
  "files": [
93
93
  "dist",
94
+ "!dist/**/*.test.*",
94
95
  "migrations",
95
96
  "README.md",
96
97
  "LICENSE",
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=index.config.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.config.test.d.ts","sourceRoot":"","sources":["../src/index.config.test.ts"],"names":[],"mappings":""}
@@ -1,87 +0,0 @@
1
- /**
2
- * createServer() hands linkforty.config.json to the redirect routes.
3
- *
4
- * The real server with only the data layer mocked: what matters is that a
5
- * config object from loadConfig() reaches the pages a visitor sees, and that
6
- * options passed in code still take precedence over it.
7
- */
8
- import { describe, it, expect, vi, afterEach } from 'vitest';
9
- // vi.mock is hoisted above these imports, so index.js still receives the mock.
10
- import { createServer, parseConfig } from './index.js';
11
- const query = vi.fn();
12
- vi.mock('./lib/database.js', () => ({
13
- SCHEMA_INIT_LOCK_KEY: 0,
14
- db: { query: (...args) => query(...args) },
15
- initializeDatabase: vi.fn(async () => undefined),
16
- }));
17
- const DESKTOP_UA = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0 Safari/537.36';
18
- function mockLink(row) {
19
- query.mockReset();
20
- query.mockImplementation(async (sql) => {
21
- if (/FROM links l/i.test(sql))
22
- return { rows: row ? [row] : [], rowCount: row ? 1 : 0 };
23
- return { rows: [], rowCount: 0 };
24
- });
25
- }
26
- const link = {
27
- id: '00000000-0000-0000-0000-0000000000aa',
28
- short_code: 'abc123',
29
- original_url: null,
30
- web_fallback_url: 'https://example.com/page',
31
- ios_app_store_url: 'https://apps.apple.com/app/id1',
32
- android_app_store_url: null,
33
- launchpad_mode: 'inherit',
34
- is_active: true,
35
- targeting_rules: null,
36
- org_settings: null,
37
- };
38
- let server;
39
- afterEach(async () => {
40
- await new Promise((r) => setImmediate(r));
41
- await server?.close();
42
- server = undefined;
43
- });
44
- const visit = (url) => server.inject({ method: 'GET', url, headers: { 'user-agent': DESKTOP_UA, accept: 'text/html' } });
45
- describe('createServer config', () => {
46
- it('serves the not-found page and Launchpad from the config file', async () => {
47
- const config = parseConfig({
48
- notFound: { title: 'Nothing here' },
49
- launchpad: { desktop: 'always', appName: 'Instance App' },
50
- });
51
- server = await createServer({ logger: false, config });
52
- mockLink(null);
53
- expect((await visit('/nosuchcode')).body).toContain('<h1>Nothing here</h1>');
54
- mockLink(link);
55
- const page = await visit('/abc123');
56
- expect(page.statusCode).toBe(200);
57
- expect(page.body).toContain('<span>Instance App</span>');
58
- });
59
- it('keeps hooks passed in code alongside the config defaults', async () => {
60
- const resolveContent = vi.fn().mockReturnValue(null);
61
- server = await createServer({
62
- logger: false,
63
- config: parseConfig({ launchpad: { desktop: 'always' } }),
64
- redirect: { launchpad: { resolveContent } },
65
- });
66
- mockLink(link);
67
- expect((await visit('/abc123')).statusCode).toBe(200);
68
- expect(resolveContent).toHaveBeenCalledOnce();
69
- });
70
- it('lets options in code take precedence over the file', async () => {
71
- server = await createServer({
72
- logger: false,
73
- config: parseConfig({ notFound: { title: 'From file' }, launchpad: { desktop: 'always' } }),
74
- redirect: { notFoundDefaults: { title: 'From code' }, launchpad: { defaults: { desktop: 'off' } } },
75
- });
76
- mockLink(null);
77
- expect((await visit('/nosuchcode')).body).toContain('<h1>From code</h1>');
78
- mockLink(link);
79
- expect((await visit('/abc123')).statusCode).toBe(302);
80
- });
81
- it('behaves as before without a config', async () => {
82
- server = await createServer({ logger: false });
83
- mockLink(link);
84
- expect((await visit('/abc123')).statusCode).toBe(302);
85
- });
86
- });
87
- //# sourceMappingURL=index.config.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.config.test.js","sourceRoot":"","sources":["../src/index.config.test.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=bot-detection.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"bot-detection.test.d.ts","sourceRoot":"","sources":["../../src/lib/bot-detection.test.ts"],"names":[],"mappings":""}
@@ -1,65 +0,0 @@
1
- import { describe, it, expect, afterEach } from 'vitest';
2
- import { classifyBot, edgeBotSignal, isSdkRequest } from './bot-detection.js';
3
- const CHROME = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0 Safari/537.36';
4
- describe('classifyBot', () => {
5
- it('flags known crawlers/scrapers by user-agent', () => {
6
- expect(classifyBot('Googlebot/2.1 (+http://www.google.com/bot.html)', 'GET')).toEqual({ isBot: true, reason: 'ua' });
7
- expect(classifyBot('facebookexternalhit/1.1', 'GET').isBot).toBe(true);
8
- expect(classifyBot('curl/8.4.0', 'GET').isBot).toBe(true);
9
- });
10
- it('does not flag a normal browser', () => {
11
- expect(classifyBot(CHROME, 'GET')).toEqual({ isBot: false, reason: null });
12
- });
13
- it('flags HEAD/OPTIONS as non-human, case-insensitively', () => {
14
- expect(classifyBot(CHROME, 'HEAD')).toEqual({ isBot: true, reason: 'method' });
15
- expect(classifyBot(CHROME, 'options')).toEqual({ isBot: true, reason: 'method' });
16
- });
17
- it('honors the edge signal with highest authority', () => {
18
- // Edge wins even for a normal browser UA on a GET.
19
- expect(classifyBot(CHROME, 'GET', true)).toEqual({ isBot: true, reason: 'edge' });
20
- // An explicit false edge signal does not override real UA/method detection.
21
- expect(classifyBot('Googlebot/2.1', 'GET', false)).toEqual({ isBot: true, reason: 'ua' });
22
- });
23
- it('does not flag an SDK request by its HTTP library user-agent', () => {
24
- expect(classifyBot('okhttp/4.12.0', 'GET')).toEqual({ isBot: true, reason: 'ua' });
25
- expect(classifyBot('okhttp/4.12.0', 'GET', undefined, true)).toEqual({ isBot: false, reason: null });
26
- expect(classifyBot('okhttp/5.5.0', 'GET', undefined, true).isBot).toBe(false);
27
- });
28
- it('still applies the method and edge signals to SDK requests', () => {
29
- expect(classifyBot('okhttp/4.12.0', 'HEAD', undefined, true)).toEqual({ isBot: true, reason: 'method' });
30
- expect(classifyBot('okhttp/4.12.0', 'GET', true, true)).toEqual({ isBot: true, reason: 'edge' });
31
- });
32
- it('handles a missing/empty user-agent', () => {
33
- expect(classifyBot(undefined, 'GET')).toEqual({ isBot: false, reason: null });
34
- expect(classifyBot('', 'GET').isBot).toBe(false);
35
- });
36
- });
37
- describe('isSdkRequest', () => {
38
- it('is true when X-LinkForty-SDK names an SDK', () => {
39
- expect(isSdkRequest({ 'x-linkforty-sdk': 'android/1.4.0' })).toBe(true);
40
- expect(isSdkRequest({ 'x-linkforty-sdk': ['react-native/1.6.2'] })).toBe(true);
41
- });
42
- it('is false when the header is missing or empty', () => {
43
- expect(isSdkRequest({})).toBe(false);
44
- expect(isSdkRequest({ 'x-linkforty-sdk': '' })).toBe(false);
45
- expect(isSdkRequest({ 'x-linkforty-sdk': ' ' })).toBe(false);
46
- });
47
- });
48
- describe('edgeBotSignal', () => {
49
- afterEach(() => {
50
- delete process.env.TRUST_EDGE_BOT_HEADER;
51
- });
52
- it('is ignored unless TRUST_EDGE_BOT_HEADER=true', () => {
53
- expect(edgeBotSignal('1')).toBeUndefined();
54
- });
55
- it('parses the header only when trusted', () => {
56
- process.env.TRUST_EDGE_BOT_HEADER = 'true';
57
- expect(edgeBotSignal('1')).toBe(true);
58
- expect(edgeBotSignal('true')).toBe(true);
59
- expect(edgeBotSignal('TRUE')).toBe(true);
60
- expect(edgeBotSignal('0')).toBe(false);
61
- expect(edgeBotSignal(['1'])).toBe(true);
62
- expect(edgeBotSignal(undefined)).toBeUndefined();
63
- });
64
- });
65
- //# sourceMappingURL=bot-detection.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"bot-detection.test.js","sourceRoot":"","sources":["../../src/lib/bot-detection.test.ts"],"names":[],"mappings":"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"}
@@ -1,7 +0,0 @@
1
- declare global {
2
- var __capturedInstallFingerprint: {
3
- ipAddress: string;
4
- } | null;
5
- }
6
- export {};
7
- //# sourceMappingURL=client-ip.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"client-ip.test.d.ts","sourceRoot":"","sources":["../../src/lib/client-ip.test.ts"],"names":[],"mappings":"AAIA,OAAO,CAAC,MAAM,CAAC;IACb,IAAI,4BAA4B,EAAE;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CAChE"}
@@ -1,114 +0,0 @@
1
- import { describe, it, expect, vi, afterEach } from 'vitest';
2
- import { getClientIp } from './client-ip';
3
- describe('getClientIp', () => {
4
- it('returns request.ip when set', () => {
5
- const request = { ip: '192.168.1.1' };
6
- expect(getClientIp(request)).toBe('192.168.1.1');
7
- });
8
- it('returns raw.socket.remoteAddress when request.ip is undefined', () => {
9
- const request = {
10
- ip: undefined,
11
- raw: { socket: { remoteAddress: '10.0.0.2' } },
12
- };
13
- expect(getClientIp(request)).toBe('10.0.0.2');
14
- });
15
- it('unwraps IPv6-mapped IPv4', () => {
16
- const request = { ip: '::ffff:192.168.1.1' };
17
- expect(getClientIp(request)).toBe('192.168.1.1');
18
- });
19
- it('returns empty string when neither ip nor socket.remoteAddress is available', () => {
20
- const request = { ip: undefined, raw: { socket: {} } };
21
- expect(getClientIp(request)).toBe('');
22
- });
23
- it('returns empty string when request.raw has no socket', () => {
24
- const request = { ip: undefined, raw: {} };
25
- expect(getClientIp(request)).toBe('');
26
- });
27
- });
28
- describe('getClientIp with TRUSTED_CLIENT_IP_HEADER', () => {
29
- const ORIGINAL = process.env.TRUSTED_CLIENT_IP_HEADER;
30
- afterEach(() => {
31
- if (ORIGINAL === undefined)
32
- delete process.env.TRUSTED_CLIENT_IP_HEADER;
33
- else
34
- process.env.TRUSTED_CLIENT_IP_HEADER = ORIGINAL;
35
- });
36
- it('prefers the configured header over request.ip', () => {
37
- process.env.TRUSTED_CLIENT_IP_HEADER = 'cf-connecting-ip';
38
- const request = {
39
- ip: '162.158.23.75', // a Cloudflare edge IP
40
- headers: { 'cf-connecting-ip': '203.0.113.50' },
41
- };
42
- expect(getClientIp(request)).toBe('203.0.113.50');
43
- });
44
- it('falls back to request.ip when the configured header is absent', () => {
45
- process.env.TRUSTED_CLIENT_IP_HEADER = 'cf-connecting-ip';
46
- const request = { ip: '203.0.113.50', headers: {} };
47
- expect(getClientIp(request)).toBe('203.0.113.50');
48
- });
49
- it('takes the first entry of a comma-separated header value', () => {
50
- process.env.TRUSTED_CLIENT_IP_HEADER = 'true-client-ip';
51
- const request = {
52
- ip: '10.0.0.1',
53
- headers: { 'true-client-ip': '203.0.113.50, 70.0.0.1' },
54
- };
55
- expect(getClientIp(request)).toBe('203.0.113.50');
56
- });
57
- it('ignores the header when the env var is unset (default behavior)', () => {
58
- delete process.env.TRUSTED_CLIENT_IP_HEADER;
59
- const request = {
60
- ip: '203.0.113.50',
61
- headers: { 'cf-connecting-ip': '1.2.3.4' },
62
- };
63
- expect(getClientIp(request)).toBe('203.0.113.50');
64
- });
65
- });
66
- describe('getClientIp with Fastify trustProxy (proxied request)', () => {
67
- it('uses X-Forwarded-For when trustProxy is true', async () => {
68
- const Fastify = (await import('fastify')).default;
69
- const { getClientIp: getIp } = await import('./client-ip.js');
70
- const app = Fastify({ trustProxy: true });
71
- app.get('/ip', async (request, reply) => {
72
- return reply.send({ ip: getIp(request) });
73
- });
74
- const res = await app.inject({
75
- method: 'GET',
76
- url: '/ip',
77
- headers: { 'x-forwarded-for': '203.0.113.50' },
78
- });
79
- expect(res.statusCode).toBe(200);
80
- const body = res.json();
81
- expect(body.ip).toBe('203.0.113.50');
82
- });
83
- });
84
- vi.mock('./fingerprint.js', async (importOriginal) => {
85
- const mod = (await importOriginal());
86
- return {
87
- ...mod,
88
- recordInstallEvent: vi.fn().mockImplementation(async (data) => {
89
- globalThis.__capturedInstallFingerprint = data;
90
- return { installId: 'test-id', match: null, deepLinkData: null };
91
- }),
92
- };
93
- });
94
- describe('SDK install does not trust client-provided ipAddress', () => {
95
- it('uses connection/proxy IP for attribution, not body ipAddress', async () => {
96
- globalThis.__capturedInstallFingerprint = null;
97
- const Fastify = (await import('fastify')).default;
98
- const { sdkRoutes } = await import('../routes/sdk.js');
99
- const app = Fastify({ trustProxy: true });
100
- await app.register(sdkRoutes);
101
- const res = await app.inject({
102
- method: 'POST',
103
- url: '/api/sdk/v1/install',
104
- payload: { ipAddress: '1.2.3.4', userAgent: 'Mozilla/5.0 Test' },
105
- headers: { 'x-forwarded-for': '203.0.113.50', 'content-type': 'application/json' },
106
- });
107
- expect(res.statusCode).toBe(200);
108
- expect(globalThis.__capturedInstallFingerprint).not.toBeNull();
109
- expect(globalThis.__capturedInstallFingerprint.ipAddress).toBe('203.0.113.50');
110
- const body = res.json();
111
- expect(body.clientReportedIp).toBe('1.2.3.4');
112
- });
113
- });
114
- //# sourceMappingURL=client-ip.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"client-ip.test.js","sourceRoot":"","sources":["../../src/lib/client-ip.test.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=config.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"config.test.d.ts","sourceRoot":"","sources":["../../src/lib/config.test.ts"],"names":[],"mappings":""}
@@ -1,126 +0,0 @@
1
- import { describe, it, expect, beforeEach, afterEach } from 'vitest';
2
- import { mkdtempSync, rmSync, writeFileSync } from 'fs';
3
- import { tmpdir } from 'os';
4
- import { join } from 'path';
5
- import { ConfigError, loadConfig, parseConfig } from './config.js';
6
- let dir;
7
- beforeEach(() => {
8
- dir = mkdtempSync(join(tmpdir(), 'linkforty-config-'));
9
- });
10
- afterEach(() => {
11
- rmSync(dir, { recursive: true, force: true });
12
- });
13
- function write(name, contents) {
14
- const path = join(dir, name);
15
- writeFileSync(path, typeof contents === 'string' ? contents : JSON.stringify(contents));
16
- return path;
17
- }
18
- function errorFrom(fn) {
19
- try {
20
- fn();
21
- }
22
- catch (error) {
23
- expect(error).toBeInstanceOf(ConfigError);
24
- return error;
25
- }
26
- throw new Error('expected a ConfigError');
27
- }
28
- describe('loadConfig', () => {
29
- it('uses the defaults when there is no file', () => {
30
- expect(loadConfig({ cwd: dir, env: {} })).toEqual({ config: {}, path: null });
31
- });
32
- it('reads linkforty.config.json from the working directory', () => {
33
- const path = write('linkforty.config.json', { notFound: { title: 'Gone' } });
34
- expect(loadConfig({ cwd: dir, env: {} })).toEqual({ config: { notFound: { title: 'Gone' } }, path });
35
- });
36
- it('reads the file named by LINKFORTY_CONFIG', () => {
37
- const path = write('custom.json', { notFound: { redirectUrl: 'https://example.com/' } });
38
- expect(loadConfig({ cwd: '/', env: { LINKFORTY_CONFIG: path } }).config).toEqual({
39
- notFound: { redirectUrl: 'https://example.com/' },
40
- });
41
- });
42
- it('fails when a named file is missing', () => {
43
- const error = errorFrom(() => loadConfig({ cwd: dir, env: { LINKFORTY_CONFIG: 'missing.json' } }));
44
- expect(error.message).toContain('missing.json: file not found');
45
- });
46
- it('fails on invalid JSON', () => {
47
- write('linkforty.config.json', '{ "notFound": { title: "x" } }');
48
- expect(errorFrom(() => loadConfig({ cwd: dir, env: {} })).message).toContain('not valid JSON');
49
- });
50
- it('trims values', () => {
51
- write('linkforty.config.json', { notFound: { title: ' Gone ' } });
52
- expect(loadConfig({ cwd: dir, env: {} }).config.notFound?.title).toBe('Gone');
53
- });
54
- });
55
- describe('parseConfig', () => {
56
- it('accepts every notFound setting', () => {
57
- const notFound = {
58
- redirectUrl: 'https://example.com/',
59
- title: 'Gone',
60
- message: 'Try the homepage.',
61
- logoUrl: 'https://cdn.example.com/logo.png',
62
- accentColor: '#0f766e',
63
- backgroundColor: '#f6f7f8',
64
- buttonLabel: 'Home',
65
- buttonUrl: 'https://example.com/',
66
- };
67
- expect(parseConfig({ notFound })).toEqual({ notFound });
68
- });
69
- it.each([
70
- [{ notFound: { redirectUrl: 'javascript:alert(1)' } }, 'notFound.redirectUrl: must be an http(s) URL'],
71
- [{ notFound: { accentColor: 'teal' } }, 'notFound.accentColor: must be a hex color'],
72
- [{ notFound: { buttonLabel: 'Home' } }, 'buttonLabel and buttonUrl must be set together'],
73
- [{ notFound: { titel: 'Gone' } }, 'notFound: unknown setting "titel"'],
74
- [{ notfound: {} }, 'unknown setting "notfound"'],
75
- [{ notFound: { title: 42 } }, 'notFound.title'],
76
- [{ notFound: { title: 'x'.repeat(121) } }, 'notFound.title'],
77
- ])('names the bad setting: %j', (raw, expected) => {
78
- const error = errorFrom(() => parseConfig(raw, 'linkforty.config.json'));
79
- expect(error.message).toContain('linkforty.config.json: ');
80
- expect(error.message).toContain(expected);
81
- });
82
- it('accepts every launchpad setting', () => {
83
- const launchpad = {
84
- desktop: 'always',
85
- mobile: 'page',
86
- appName: 'Example App',
87
- appIconUrl: 'https://cdn.example.com/icon.png',
88
- appWebsiteUrl: 'https://example.com',
89
- accentColor: '#0f766e',
90
- backgroundColor: '#101418',
91
- };
92
- expect(parseConfig({ launchpad })).toEqual({ launchpad });
93
- });
94
- it.each([
95
- [{ launchpad: { desktop: 'sometimes' } }, 'launchpad.desktop'],
96
- [{ launchpad: { accentColor: '#abc' } }, 'launchpad.accentColor: must be a six-digit hex color'],
97
- [{ launchpad: { appIconUrl: 'ftp://cdn.example/icon.png' } }, 'launchpad.appIconUrl: must be an http(s) URL'],
98
- [{ launchpad: { templateId: 'hero-1' } }, 'launchpad: unknown setting "templateId"'],
99
- [{ launchpad: { appname: 'x' } }, 'launchpad: unknown setting "appname"'],
100
- [{ launchpad: { appName: 'x'.repeat(61) } }, 'launchpad.appName'],
101
- ])('names the bad launchpad setting: %j', (raw, expected) => {
102
- expect(errorFrom(() => parseConfig(raw)).message).toContain(expected);
103
- });
104
- it('rejects a file that is not an object', () => {
105
- expect(() => parseConfig([])).toThrow(ConfigError);
106
- });
107
- });
108
- describe('botDetection', () => {
109
- it('accepts a list of scanner networks', () => {
110
- expect(parseConfig({ botDetection: { emailScannerAsns: [8075, 16509] } })).toEqual({
111
- botDetection: { emailScannerAsns: [8075, 16509] },
112
- });
113
- expect(parseConfig({ botDetection: { emailScannerAsns: [] } })).toEqual({ botDetection: { emailScannerAsns: [] } });
114
- });
115
- it('rejects networks iCloud Private Relay exits through', () => {
116
- const error = errorFrom(() => parseConfig({ botDetection: { emailScannerAsns: [8075, 13335] } }));
117
- expect(error.message).toContain('botDetection.emailScannerAsns');
118
- expect(error.message).toContain('Private Relay');
119
- });
120
- it('rejects malformed ASNs and unknown keys', () => {
121
- expect(() => parseConfig({ botDetection: { emailScannerAsns: ['8075'] } })).toThrow(ConfigError);
122
- expect(() => parseConfig({ botDetection: { emailScannerAsns: [-1] } })).toThrow(ConfigError);
123
- expect(() => parseConfig({ botDetection: { scanners: true } })).toThrow(ConfigError);
124
- });
125
- });
126
- //# sourceMappingURL=config.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"config.test.js","sourceRoot":"","sources":["../../src/lib/config.test.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=database.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"database.test.d.ts","sourceRoot":"","sources":["../../src/lib/database.test.ts"],"names":[],"mappings":""}