deeplink-doctor 1.0.1

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 (112) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/LICENSE +21 -0
  3. package/README.md +188 -0
  4. package/dist/checks/calculateExitCode.d.ts +4 -0
  5. package/dist/checks/calculateExitCode.js +4 -0
  6. package/dist/checks/calculateExitCode.js.map +1 -0
  7. package/dist/checks/checkAasaAppIds.d.ts +2 -0
  8. package/dist/checks/checkAasaAppIds.js +15 -0
  9. package/dist/checks/checkAasaAppIds.js.map +1 -0
  10. package/dist/checks/checkAppIdentifiers.d.ts +2 -0
  11. package/dist/checks/checkAppIdentifiers.js +13 -0
  12. package/dist/checks/checkAppIdentifiers.js.map +1 -0
  13. package/dist/checks/checkAssetlinks.d.ts +2 -0
  14. package/dist/checks/checkAssetlinks.js +21 -0
  15. package/dist/checks/checkAssetlinks.js.map +1 -0
  16. package/dist/checks/checkAssociatedDomains.d.ts +3 -0
  17. package/dist/checks/checkAssociatedDomains.js +7 -0
  18. package/dist/checks/checkAssociatedDomains.js.map +1 -0
  19. package/dist/checks/checkAutoVerifyHosts.d.ts +2 -0
  20. package/dist/checks/checkAutoVerifyHosts.js +6 -0
  21. package/dist/checks/checkAutoVerifyHosts.js.map +1 -0
  22. package/dist/checks/checkConfig.d.ts +2 -0
  23. package/dist/checks/checkConfig.js +11 -0
  24. package/dist/checks/checkConfig.js.map +1 -0
  25. package/dist/checks/checkDeadLinks.d.ts +2 -0
  26. package/dist/checks/checkDeadLinks.js +9 -0
  27. package/dist/checks/checkDeadLinks.js.map +1 -0
  28. package/dist/checks/checkRemote.d.ts +2 -0
  29. package/dist/checks/checkRemote.js +4 -0
  30. package/dist/checks/checkRemote.js.map +1 -0
  31. package/dist/checks/checkScheme.d.ts +3 -0
  32. package/dist/checks/checkScheme.js +13 -0
  33. package/dist/checks/checkScheme.js.map +1 -0
  34. package/dist/checks/checkUnreachableRoutes.d.ts +2 -0
  35. package/dist/checks/checkUnreachableRoutes.js +11 -0
  36. package/dist/checks/checkUnreachableRoutes.js.map +1 -0
  37. package/dist/checks/runChecks.d.ts +2 -0
  38. package/dist/checks/runChecks.js +8 -0
  39. package/dist/checks/runChecks.js.map +1 -0
  40. package/dist/checks/targetMatchesRoute.d.ts +2 -0
  41. package/dist/checks/targetMatchesRoute.js +14 -0
  42. package/dist/checks/targetMatchesRoute.js.map +1 -0
  43. package/dist/commands/check.d.ts +21 -0
  44. package/dist/commands/check.js +42 -0
  45. package/dist/commands/check.js.map +1 -0
  46. package/dist/config/findingExplanations.d.ts +2 -0
  47. package/dist/config/findingExplanations.js +19 -0
  48. package/dist/config/findingExplanations.js.map +1 -0
  49. package/dist/config/findingSeverities.d.ts +2 -0
  50. package/dist/config/findingSeverities.js +16 -0
  51. package/dist/config/findingSeverities.js.map +1 -0
  52. package/dist/index.d.ts +2 -0
  53. package/dist/index.js +59 -0
  54. package/dist/index.js.map +1 -0
  55. package/dist/lib/generateFinding.d.ts +5 -0
  56. package/dist/lib/generateFinding.js +8 -0
  57. package/dist/lib/generateFinding.js.map +1 -0
  58. package/dist/links/extractDomains.d.ts +2 -0
  59. package/dist/links/extractDomains.js +11 -0
  60. package/dist/links/extractDomains.js.map +1 -0
  61. package/dist/links/extractLinkConfig.d.ts +2 -0
  62. package/dist/links/extractLinkConfig.js +15 -0
  63. package/dist/links/extractLinkConfig.js.map +1 -0
  64. package/dist/links/extractLinkTargets.d.ts +2 -0
  65. package/dist/links/extractLinkTargets.js +25 -0
  66. package/dist/links/extractLinkTargets.js.map +1 -0
  67. package/dist/parsers/expoConfig.d.ts +4 -0
  68. package/dist/parsers/expoConfig.js +16 -0
  69. package/dist/parsers/expoConfig.js.map +1 -0
  70. package/dist/parsers/routes.d.ts +2 -0
  71. package/dist/parsers/routes.js +23 -0
  72. package/dist/parsers/routes.js.map +1 -0
  73. package/dist/report/human.d.ts +3 -0
  74. package/dist/report/human.js +72 -0
  75. package/dist/report/human.js.map +1 -0
  76. package/dist/report/json.d.ts +3 -0
  77. package/dist/report/json.js +19 -0
  78. package/dist/report/json.js.map +1 -0
  79. package/dist/routes/parseRoutePath.d.ts +3 -0
  80. package/dist/routes/parseRoutePath.js +53 -0
  81. package/dist/routes/parseRoutePath.js.map +1 -0
  82. package/dist/routes/routeHandlesPath.d.ts +2 -0
  83. package/dist/routes/routeHandlesPath.js +12 -0
  84. package/dist/routes/routeHandlesPath.js.map +1 -0
  85. package/dist/routes/routeHandlesPrefix.d.ts +2 -0
  86. package/dist/routes/routeHandlesPrefix.js +15 -0
  87. package/dist/routes/routeHandlesPrefix.js.map +1 -0
  88. package/dist/sources/aasa.d.ts +2 -0
  89. package/dist/sources/aasa.js +16 -0
  90. package/dist/sources/aasa.js.map +1 -0
  91. package/dist/sources/assetlinks.d.ts +2 -0
  92. package/dist/sources/assetlinks.js +13 -0
  93. package/dist/sources/assetlinks.js.map +1 -0
  94. package/dist/sources/httpFetcher.d.ts +2 -0
  95. package/dist/sources/httpFetcher.js +5 -0
  96. package/dist/sources/httpFetcher.js.map +1 -0
  97. package/dist/sources/loadAssociations.d.ts +2 -0
  98. package/dist/sources/loadAssociations.js +49 -0
  99. package/dist/sources/loadAssociations.js.map +1 -0
  100. package/dist/suppressions/applySuppressions.d.ts +5 -0
  101. package/dist/suppressions/applySuppressions.js +38 -0
  102. package/dist/suppressions/applySuppressions.js.map +1 -0
  103. package/dist/suppressions/parseSuppressionConfig.d.ts +2 -0
  104. package/dist/suppressions/parseSuppressionConfig.js +28 -0
  105. package/dist/suppressions/parseSuppressionConfig.js.map +1 -0
  106. package/dist/suppressions/readSuppressionConfig.d.ts +5 -0
  107. package/dist/suppressions/readSuppressionConfig.js +32 -0
  108. package/dist/suppressions/readSuppressionConfig.js.map +1 -0
  109. package/dist/types.d.ts +92 -0
  110. package/dist/types.js +15 -0
  111. package/dist/types.js.map +1 -0
  112. package/package.json +83 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loadAssociations.js","sourceRoot":"","sources":["../../src/sources/loadAssociations.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import { type Finding, type SuppressionRule } from '../types.js';
2
+ export declare const applySuppressions: (findings: Finding[], rules: SuppressionRule[]) => {
3
+ active: Finding[];
4
+ suppressed: Finding[];
5
+ };
@@ -0,0 +1,38 @@
1
+ import { generateFinding } from '../lib/generateFinding.js';
2
+ import { CHECK_CODES } from '../types.js';
3
+ const isCheckCode = (code) => CHECK_CODES.includes(code);
4
+ const matches = (rule, finding) => rule.code === finding.code &&
5
+ (!rule.route || rule.route === finding.route || rule.route === finding.target);
6
+ export const applySuppressions = (findings, rules) => {
7
+ const result = findings.reduce((acc, cur) => {
8
+ if (rules.some((rule) => matches(rule, cur))) {
9
+ return {
10
+ active: acc.active,
11
+ suppressed: [...acc.suppressed, cur],
12
+ };
13
+ }
14
+ return {
15
+ active: [...acc.active, cur],
16
+ suppressed: acc.suppressed,
17
+ };
18
+ }, { active: [], suppressed: [] });
19
+ const ruleFindings = rules.flatMap((rule) => {
20
+ const route = rule.route ? { route: rule.route } : {};
21
+ if (!isCheckCode(rule.code)) {
22
+ return [
23
+ generateFinding('DL902', `Suppression for unknown code "${rule.code}" — possible typo`, route),
24
+ ];
25
+ }
26
+ if (!rule?.reason || !rule?.owner) {
27
+ return [
28
+ generateFinding('DL901', `Suppression for ${rule.code} is missing a reason and/or owner`, route),
29
+ ];
30
+ }
31
+ return [];
32
+ });
33
+ return {
34
+ active: [...result.active, ...ruleFindings],
35
+ suppressed: result.suppressed,
36
+ };
37
+ };
38
+ //# sourceMappingURL=applySuppressions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"applySuppressions.js","sourceRoot":"","sources":["../../src/suppressions/applySuppressions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAsC,MAAM,aAAa,CAAC;AAE9E,MAAM,WAAW,GAAG,CAAC,IAAY,EAAW,EAAE,CAAE,WAAiC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AAEjG,MAAM,OAAO,GAAG,CAAC,IAAqB,EAAE,OAAgB,EAAW,EAAE,CACnE,IAAI,CAAC,IAAI,KAAK,OAAO,CAAC,IAAI;IAC1B,CAAC,CAAC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,KAAK,OAAO,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;AAEjF,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAC/B,QAAmB,EACnB,KAAwB,EACsB,EAAE;IAChD,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAC5B,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QACX,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC;YAC7C,OAAO;gBACL,MAAM,EAAE,GAAG,CAAC,MAAM;gBAClB,UAAU,EAAE,CAAC,GAAG,GAAG,CAAC,UAAU,EAAE,GAAG,CAAC;aACrC,CAAC;QACJ,CAAC;QACD,OAAO;YACL,MAAM,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC;YAC5B,UAAU,EAAE,GAAG,CAAC,UAAU;SAC3B,CAAC;IACJ,CAAC,EACD,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE,EAAkD,CAC/E,CAAC;IAEF,MAAM,YAAY,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAa,EAAE;QACrD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACtD,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAC5B,OAAO;gBACL,eAAe,CACb,OAAO,EACP,iCAAiC,IAAI,CAAC,IAAI,mBAAmB,EAC7D,KAAK,CACN;aACF,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,IAAI,EAAE,MAAM,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC;YAClC,OAAO;gBACL,eAAe,CACb,OAAO,EACP,mBAAmB,IAAI,CAAC,IAAI,mCAAmC,EAC/D,KAAK,CACN;aACF,CAAC;QACJ,CAAC;QACD,OAAO,EAAE,CAAC;IACZ,CAAC,CAAC,CAAC;IAEH,OAAO;QACL,MAAM,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,YAAY,CAAC;QAC3C,UAAU,EAAE,MAAM,CAAC,UAAU;KAC9B,CAAC;AACJ,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { SuppressionRule } from '../types.js';
2
+ export declare const parseSuppressionConfig: (raw: unknown) => SuppressionRule[];
@@ -0,0 +1,28 @@
1
+ export const parseSuppressionConfig = (raw) => {
2
+ if (raw === null || raw === undefined) {
3
+ return [];
4
+ }
5
+ if (typeof raw !== 'object') {
6
+ throw new Error('deeplink config must be an object');
7
+ }
8
+ const { ignore } = raw;
9
+ if (ignore === undefined) {
10
+ return [];
11
+ }
12
+ if (!Array.isArray(ignore)) {
13
+ throw new Error('`ignore` must be an array');
14
+ }
15
+ return ignore.map((rule) => {
16
+ if (typeof rule?.code !== 'string') {
17
+ throw new Error('each ignore entry needs a string code');
18
+ }
19
+ return {
20
+ code: rule.code,
21
+ ...(rule?.route ? { route: rule.route } : {}),
22
+ ...(rule?.reason ? { reason: rule.reason } : {}),
23
+ ...(rule?.owner ? { owner: rule.owner } : {}),
24
+ ...(rule?.revisitWhen ? { revisitWhen: rule.revisitWhen } : {}),
25
+ };
26
+ });
27
+ };
28
+ //# sourceMappingURL=parseSuppressionConfig.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parseSuppressionConfig.js","sourceRoot":"","sources":["../../src/suppressions/parseSuppressionConfig.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,GAAY,EAAqB,EAAE;IACxE,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;QACtC,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;IACvD,CAAC;IAED,MAAM,EAAE,MAAM,EAAE,GAAG,GAA2B,CAAC;IAC/C,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;IAC/C,CAAC;IAED,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,IAA6B,EAAE,EAAE;QAClD,IAAI,OAAO,IAAI,EAAE,IAAI,KAAK,QAAQ,EAAE,CAAC;YACnC,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;QAC3D,CAAC;QACD,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAe,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACvD,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAgB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC1D,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAe,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACvD,GAAG,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC,WAAqB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC1E,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { SuppressionRule } from '../types.js';
2
+ export declare const CONFIG_FILENAME = "deeplink.config.json";
3
+ type ConfigReader = (projectRoot: string, configPath?: string) => string | undefined;
4
+ export declare const readSuppressionConfig: (projectRoot: string, configPath?: string, read?: ConfigReader) => SuppressionRule[];
5
+ export {};
@@ -0,0 +1,32 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { parseSuppressionConfig } from './parseSuppressionConfig.js';
4
+ export const CONFIG_FILENAME = 'deeplink.config.json';
5
+ const defaultRead = (projectRoot, configPath) => {
6
+ try {
7
+ return readFileSync(configPath ?? join(projectRoot, CONFIG_FILENAME), 'utf8');
8
+ }
9
+ catch {
10
+ return undefined;
11
+ }
12
+ };
13
+ export const readSuppressionConfig = (projectRoot, configPath, read = defaultRead) => {
14
+ const contents = read(projectRoot, configPath);
15
+ const source = configPath ?? CONFIG_FILENAME;
16
+ if (contents === undefined) {
17
+ if (configPath !== undefined) {
18
+ throw new Error(`Suppression config not found at "${configPath}".`);
19
+ }
20
+ return [];
21
+ }
22
+ try {
23
+ return parseSuppressionConfig(JSON.parse(contents));
24
+ }
25
+ catch (error) {
26
+ const reason = error instanceof Error ? error.message : String(error);
27
+ throw new Error(`Failed to read "${source}" in "${projectRoot}": ${reason}.`, {
28
+ cause: error,
29
+ });
30
+ }
31
+ };
32
+ //# sourceMappingURL=readSuppressionConfig.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"readSuppressionConfig.js","sourceRoot":"","sources":["../../src/suppressions/readSuppressionConfig.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAErE,MAAM,CAAC,MAAM,eAAe,GAAG,sBAAsB,CAAC;AAItD,MAAM,WAAW,GAAiB,CAAC,WAAW,EAAE,UAAU,EAAE,EAAE;IAC5D,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,UAAU,IAAI,IAAI,CAAC,WAAW,EAAE,eAAe,CAAC,EAAE,MAAM,CAAC,CAAC;IAChF,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,qBAAqB,GAAG,CACnC,WAAmB,EACnB,UAAmB,EACnB,OAAqB,WAAW,EACb,EAAE;IACrB,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;IAC/C,MAAM,MAAM,GAAG,UAAU,IAAI,eAAe,CAAC;IAE7C,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;YAC7B,MAAM,IAAI,KAAK,CAAC,oCAAoC,UAAU,IAAI,CAAC,CAAC;QACtE,CAAC;QACD,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,IAAI,CAAC;QACH,OAAO,sBAAsB,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC;IACtD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,MAAM,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACtE,MAAM,IAAI,KAAK,CAAC,mBAAmB,MAAM,SAAS,WAAW,MAAM,MAAM,GAAG,EAAE;YAC5E,KAAK,EAAE,KAAK;SACb,CAAC,CAAC;IACL,CAAC;AACH,CAAC,CAAC"}
@@ -0,0 +1,92 @@
1
+ export type Segment = {
2
+ kind: 'static' | 'dynamic' | 'catchall';
3
+ value: string;
4
+ };
5
+ export type PathData = {
6
+ pathname: string;
7
+ filePath: string;
8
+ segments: Segment[];
9
+ isLayout: boolean;
10
+ inGroup: boolean;
11
+ isApi: boolean;
12
+ isSpecial: boolean;
13
+ };
14
+ export type IntentFilterData = {
15
+ scheme?: string;
16
+ host?: string;
17
+ pathPrefix?: string;
18
+ pathPattern?: string;
19
+ path?: string;
20
+ };
21
+ export type IntentFilter = {
22
+ action?: string;
23
+ autoVerify?: boolean;
24
+ category?: string[];
25
+ data: IntentFilterData[];
26
+ };
27
+ export type LinkConfig = {
28
+ schemes: string[];
29
+ ios: {
30
+ bundleIdentifier?: string;
31
+ associatedDomains: string[];
32
+ };
33
+ android: {
34
+ package?: string;
35
+ intentFilters: IntentFilter[];
36
+ };
37
+ };
38
+ export type ResolvedExpoConfig = {
39
+ scheme?: string | string[];
40
+ ios?: {
41
+ bundleIdentifier?: string;
42
+ associatedDomains?: string[];
43
+ };
44
+ android?: {
45
+ package?: string;
46
+ intentFilters?: IntentFilter[];
47
+ };
48
+ };
49
+ export type LinkTarget = {
50
+ host?: string;
51
+ scheme?: string;
52
+ segments: string[];
53
+ kind: 'exact' | 'prefix' | 'pattern';
54
+ raw: string;
55
+ };
56
+ export declare const CHECK_CODES: readonly ["DL001", "DL002", "DL003", "DL101", "DL102", "DL103", "DL104", "DL201", "DL202", "DL203", "DL204"];
57
+ export type FindingCode = (typeof CHECK_CODES)[number] | 'DL901' | 'DL902';
58
+ export type Finding = {
59
+ code: FindingCode;
60
+ severity: 'warn' | 'error';
61
+ message: string;
62
+ route?: string;
63
+ target?: string;
64
+ };
65
+ export type AasaModel = {
66
+ appIDs: string[];
67
+ };
68
+ export type AssetlinkEntry = {
69
+ packageName: string;
70
+ fingerprints: string[];
71
+ };
72
+ export type HttpResponse = {
73
+ status: number;
74
+ redirected: boolean;
75
+ body: string;
76
+ };
77
+ export type Fetcher = (url: string) => Promise<HttpResponse>;
78
+ export type Associations = {
79
+ aasa: AasaModel;
80
+ assetlinks: AssetlinkEntry[];
81
+ findings: Finding[];
82
+ };
83
+ export type SuppressionRule = {
84
+ code: string;
85
+ route?: string;
86
+ reason?: string;
87
+ owner?: string;
88
+ revisitWhen?: string;
89
+ };
90
+ export type DeeplinkConfig = {
91
+ ignore: SuppressionRule[];
92
+ };
package/dist/types.js ADDED
@@ -0,0 +1,15 @@
1
+ // Codes emitted by the checks themselves (suppressible by ignore rules).
2
+ export const CHECK_CODES = [
3
+ 'DL001',
4
+ 'DL002',
5
+ 'DL003',
6
+ 'DL101',
7
+ 'DL102',
8
+ 'DL103',
9
+ 'DL104',
10
+ 'DL201',
11
+ 'DL202',
12
+ 'DL203',
13
+ 'DL204',
14
+ ];
15
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAqDA,yEAAyE;AACzE,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,OAAO;IACP,OAAO;IACP,OAAO;IACP,OAAO;IACP,OAAO;IACP,OAAO;IACP,OAAO;IACP,OAAO;IACP,OAAO;IACP,OAAO;IACP,OAAO;CACC,CAAC"}
package/package.json ADDED
@@ -0,0 +1,83 @@
1
+ {
2
+ "name": "deeplink-doctor",
3
+ "version": "1.0.1",
4
+ "description": "Statically reconcile an Expo project's route tree, native deep-link config, and hosted association files — and report where they disagree.",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "author": "Konstantinos Mavrikas <mavrikas.konstantinos@gmail.com>",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/KMavr/deeplink-doctor.git"
11
+ },
12
+ "homepage": "https://github.com/KMavr/deeplink-doctor#readme",
13
+ "bugs": "https://github.com/KMavr/deeplink-doctor/issues",
14
+ "keywords": [
15
+ "expo",
16
+ "expo-router",
17
+ "deep-link",
18
+ "universal-links",
19
+ "app-links",
20
+ "aasa",
21
+ "assetlinks",
22
+ "cli",
23
+ "linter"
24
+ ],
25
+ "bin": {
26
+ "deeplink-doctor": "./dist/index.js"
27
+ },
28
+ "files": [
29
+ "dist",
30
+ "README.md",
31
+ "LICENSE",
32
+ "CHANGELOG.md"
33
+ ],
34
+ "engines": {
35
+ "node": ">=18"
36
+ },
37
+ "publishConfig": {
38
+ "access": "public",
39
+ "provenance": true
40
+ },
41
+ "scripts": {
42
+ "build": "tsc -p tsconfig.json",
43
+ "dev": "tsc -p tsconfig.json --watch",
44
+ "start": "node dist/index.js",
45
+ "test": "vitest run",
46
+ "test:watch": "vitest",
47
+ "lint": "eslint src tests",
48
+ "typecheck": "tsc --noEmit",
49
+ "format": "prettier --write .",
50
+ "format:check": "prettier --check .",
51
+ "prepare": "node -e \"if (process.env.CI) process.exit(0)\" && husky",
52
+ "prepack": "npm run build && npm run lint && npm run typecheck && npm test"
53
+ },
54
+ "lint-staged": {
55
+ "*.{ts,js}": [
56
+ "eslint --fix",
57
+ "prettier --write"
58
+ ],
59
+ "*.{json,md,yml,yaml}": [
60
+ "prettier --write"
61
+ ]
62
+ },
63
+ "dependencies": {
64
+ "chalk": "^5.6.2",
65
+ "commander": "^15.0.0"
66
+ },
67
+ "devDependencies": {
68
+ "@commitlint/cli": "^21.0.2",
69
+ "@commitlint/config-conventional": "^21.0.2",
70
+ "@eslint/js": "^9.39.4",
71
+ "@types/node": "^22.10.0",
72
+ "eslint": "^9.39.4",
73
+ "eslint-config-prettier": "^10.1.8",
74
+ "eslint-plugin-import": "^2.32.0",
75
+ "eslint-plugin-prettier": "^5.5.5",
76
+ "husky": "^9.1.7",
77
+ "lint-staged": "^15.2.11",
78
+ "prettier": "^3.4.2",
79
+ "typescript": "^5.7.2",
80
+ "typescript-eslint": "^8.59.4",
81
+ "vitest": "^3.2.6"
82
+ }
83
+ }