@freegamestore/compliance 0.7.0 → 0.8.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 (90) hide show
  1. package/README.md +1 -1
  2. package/dist/checks/deploy-workflow.d.ts +16 -0
  3. package/dist/checks/deploy-workflow.d.ts.map +1 -0
  4. package/dist/checks/deploy-workflow.js +33 -0
  5. package/dist/checks/deploy-workflow.js.map +1 -0
  6. package/dist/checks/game-naming.d.ts +4 -0
  7. package/dist/checks/game-naming.d.ts.map +1 -0
  8. package/dist/checks/game-naming.js +98 -0
  9. package/dist/checks/game-naming.js.map +1 -0
  10. package/dist/checks/gitignore-complete.d.ts +4 -0
  11. package/dist/checks/gitignore-complete.d.ts.map +1 -0
  12. package/dist/checks/gitignore-complete.js +51 -0
  13. package/dist/checks/gitignore-complete.js.map +1 -0
  14. package/dist/checks/no-any-types.d.ts +4 -0
  15. package/dist/checks/no-any-types.d.ts.map +1 -0
  16. package/dist/checks/no-any-types.js +72 -0
  17. package/dist/checks/no-any-types.js.map +1 -0
  18. package/dist/checks/no-brand-overrides.d.ts.map +1 -1
  19. package/dist/checks/no-brand-overrides.js +14 -0
  20. package/dist/checks/no-brand-overrides.js.map +1 -1
  21. package/dist/checks/no-console-log.d.ts +4 -0
  22. package/dist/checks/no-console-log.d.ts.map +1 -0
  23. package/dist/checks/no-console-log.js +63 -0
  24. package/dist/checks/no-console-log.js.map +1 -0
  25. package/dist/checks/no-cookies.d.ts +13 -0
  26. package/dist/checks/no-cookies.d.ts.map +1 -0
  27. package/dist/checks/no-cookies.js +64 -0
  28. package/dist/checks/no-cookies.js.map +1 -0
  29. package/dist/checks/no-excessive-inline-styles.d.ts +4 -0
  30. package/dist/checks/no-excessive-inline-styles.d.ts.map +1 -0
  31. package/dist/checks/no-excessive-inline-styles.js +82 -0
  32. package/dist/checks/no-excessive-inline-styles.js.map +1 -0
  33. package/dist/checks/no-external-fetch.d.ts +4 -0
  34. package/dist/checks/no-external-fetch.d.ts.map +1 -0
  35. package/dist/checks/no-external-fetch.js +102 -0
  36. package/dist/checks/no-external-fetch.js.map +1 -0
  37. package/dist/checks/no-external-scripts.d.ts +16 -0
  38. package/dist/checks/no-external-scripts.d.ts.map +1 -0
  39. package/dist/checks/no-external-scripts.js +91 -0
  40. package/dist/checks/no-external-scripts.js.map +1 -0
  41. package/dist/checks/no-hardcoded-colors.d.ts +4 -0
  42. package/dist/checks/no-hardcoded-colors.d.ts.map +1 -0
  43. package/dist/checks/no-hardcoded-colors.js +79 -0
  44. package/dist/checks/no-hardcoded-colors.js.map +1 -0
  45. package/dist/checks/no-payment-sdk.d.ts +13 -0
  46. package/dist/checks/no-payment-sdk.d.ts.map +1 -0
  47. package/dist/checks/no-payment-sdk.js +118 -0
  48. package/dist/checks/no-payment-sdk.js.map +1 -0
  49. package/dist/checks/no-scroll.js +1 -1
  50. package/dist/checks/no-scroll.js.map +1 -1
  51. package/dist/checks/no-tracking.js +6 -6
  52. package/dist/checks/no-tracking.js.map +1 -1
  53. package/dist/checks/pwa-icons.d.ts +15 -0
  54. package/dist/checks/pwa-icons.d.ts.map +1 -0
  55. package/dist/checks/pwa-icons.js +38 -0
  56. package/dist/checks/pwa-icons.js.map +1 -0
  57. package/dist/checks/react-strict-mode.d.ts +4 -0
  58. package/dist/checks/react-strict-mode.d.ts.map +1 -0
  59. package/dist/checks/react-strict-mode.js +43 -0
  60. package/dist/checks/react-strict-mode.js.map +1 -0
  61. package/dist/checks/sdk-version.d.ts +4 -0
  62. package/dist/checks/sdk-version.d.ts.map +1 -0
  63. package/dist/checks/sdk-version.js +80 -0
  64. package/dist/checks/sdk-version.js.map +1 -0
  65. package/dist/checks/tech-versions.d.ts +4 -0
  66. package/dist/checks/tech-versions.d.ts.map +1 -0
  67. package/dist/checks/tech-versions.js +100 -0
  68. package/dist/checks/tech-versions.js.map +1 -0
  69. package/dist/checks/typescript-strict.d.ts +14 -0
  70. package/dist/checks/typescript-strict.d.ts.map +1 -0
  71. package/dist/checks/typescript-strict.js +155 -0
  72. package/dist/checks/typescript-strict.js.map +1 -0
  73. package/dist/checks/uses-game-sdk.d.ts +16 -0
  74. package/dist/checks/uses-game-sdk.d.ts.map +1 -0
  75. package/dist/checks/uses-game-sdk.js +82 -0
  76. package/dist/checks/uses-game-sdk.js.map +1 -0
  77. package/dist/checks/uses-localstorage.d.ts +14 -0
  78. package/dist/checks/uses-localstorage.d.ts.map +1 -0
  79. package/dist/checks/uses-localstorage.js +45 -0
  80. package/dist/checks/uses-localstorage.js.map +1 -0
  81. package/dist/index.d.ts +19 -1
  82. package/dist/index.d.ts.map +1 -1
  83. package/dist/index.js +44 -2
  84. package/dist/index.js.map +1 -1
  85. package/dist/lib/strip.js +4 -3
  86. package/dist/lib/strip.js.map +1 -1
  87. package/dist/live/index.d.ts.map +1 -1
  88. package/dist/live/index.js +9 -4
  89. package/dist/live/index.js.map +1 -1
  90. package/package.json +1 -1
@@ -0,0 +1,82 @@
1
+ import { stripCommentsAndStrings } from '../lib/strip.js';
2
+ /**
3
+ * Flags excessive use of React inline style objects (`style={{ ... }}`)
4
+ * in TSX files under web/src/. Some inline styles are fine — dynamic
5
+ * values, canvas positioning, animation transforms. But heavy reliance
6
+ * on `style={{` means the game isn't leveraging Tailwind CSS or the
7
+ * design system, making theming and dark mode harder.
8
+ *
9
+ * Thresholds:
10
+ * - Any single file with > 15 inline style objects → warn
11
+ * - Total across all TSX files > 30 → warn
12
+ *
13
+ * Strips comments before scanning. Excludes test files.
14
+ *
15
+ * WARN level — guidelines, not a hard gate.
16
+ */
17
+ const PER_FILE_THRESHOLD = 15;
18
+ const TOTAL_THRESHOLD = 30;
19
+ const INLINE_STYLE_RE = /\bstyle\s*=\s*\{\{/g;
20
+ function extOf(path) {
21
+ const dot = path.lastIndexOf('.');
22
+ const slash = path.lastIndexOf('/');
23
+ return dot > slash ? path.slice(dot).toLowerCase() : '';
24
+ }
25
+ function isTestFile(path) {
26
+ return /\.(?:test|spec)\.[jt]sx?$/.test(path) || /(?:^|\/)(?:test|tests|__tests__)\//.test(path);
27
+ }
28
+ export async function checkNoExcessiveInlineStyles(source) {
29
+ let totalCount = 0;
30
+ const heavyFiles = [];
31
+ let fileCount = 0;
32
+ for await (const path of source.list()) {
33
+ if (!path.startsWith('web/src/'))
34
+ continue;
35
+ if (extOf(path) !== '.tsx')
36
+ continue;
37
+ if (isTestFile(path))
38
+ continue;
39
+ const raw = await source.read(path);
40
+ if (!raw)
41
+ continue;
42
+ const stripped = stripCommentsAndStrings(raw);
43
+ const matches = stripped.match(INLINE_STYLE_RE);
44
+ const count = matches ? matches.length : 0;
45
+ if (count > 0) {
46
+ totalCount += count;
47
+ fileCount++;
48
+ if (count > PER_FILE_THRESHOLD) {
49
+ heavyFiles.push({ file: path, count });
50
+ }
51
+ }
52
+ }
53
+ const perFileViolation = heavyFiles.length > 0;
54
+ const totalViolation = totalCount > TOTAL_THRESHOLD;
55
+ if (!perFileViolation && !totalViolation) {
56
+ return {
57
+ name: 'No excessive inline styles',
58
+ status: 'pass',
59
+ detail: `${totalCount} inline style(s) across ${fileCount} TSX file(s) (thresholds: ${PER_FILE_THRESHOLD}/file, ${TOTAL_THRESHOLD} total)`,
60
+ };
61
+ }
62
+ const parts = [];
63
+ if (totalViolation) {
64
+ parts.push(`${totalCount} total inline styles (threshold: ${TOTAL_THRESHOLD})`);
65
+ }
66
+ if (perFileViolation) {
67
+ parts.push(`${heavyFiles.length} file(s) exceed ${PER_FILE_THRESHOLD}/file: ${heavyFiles
68
+ .slice(0, 3)
69
+ .map((h) => `${h.file} (${h.count})`)
70
+ .join(', ')}${heavyFiles.length > 3 ? '...' : ''}`);
71
+ }
72
+ return {
73
+ name: 'No excessive inline styles',
74
+ status: 'warn',
75
+ detail: parts.join('; '),
76
+ suggestions: [
77
+ 'Replace inline style objects with Tailwind CSS utility classes where possible.',
78
+ 'Keep inline styles for truly dynamic values (e.g. computed positions, animation transforms).',
79
+ ],
80
+ };
81
+ }
82
+ //# sourceMappingURL=no-excessive-inline-styles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-excessive-inline-styles.js","sourceRoot":"","sources":["../../src/checks/no-excessive-inline-styles.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { FileSource } from '../lib/file-source.js';
2
+ import type { CheckResult } from '../types.js';
3
+ export declare function checkNoExternalFetch(source: FileSource): Promise<CheckResult>;
4
+ //# sourceMappingURL=no-external-fetch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-external-fetch.d.ts","sourceRoot":"","sources":["../../src/checks/no-external-fetch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAExD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAmD/C,wBAAsB,oBAAoB,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC,CA4DnF"}
@@ -0,0 +1,102 @@
1
+ import { stripCommentsOnly } from '../lib/strip.js';
2
+ /**
3
+ * Flags fetch() and XMLHttpRequest calls to external domains in game
4
+ * source files. Games on the free tier must be self-contained — external
5
+ * API calls violate both the privacy mandate (data leaves the platform)
6
+ * and the offline/PWA mandate (game breaks without network).
7
+ *
8
+ * Allowed origins:
9
+ * - Relative URLs (`fetch('/api/...')`)
10
+ * - freegamestore.online (and subdomains)
11
+ * - freeappstore.online (and subdomains)
12
+ * - localhost / 127.0.0.1 (dev)
13
+ *
14
+ * Scans .ts and .tsx files under web/src/. Strips comments before
15
+ * scanning so commented-out fetches don't trigger false positives.
16
+ * String contents are preserved — the URLs we're looking for live
17
+ * inside string literals.
18
+ *
19
+ * ERROR level — external fetches are a hard compliance gate.
20
+ */
21
+ const SCAN_EXTS = new Set(['.ts', '.tsx']);
22
+ const ALLOWED_DOMAINS = [
23
+ 'freegamestore.online',
24
+ 'freeappstore.online',
25
+ 'localhost',
26
+ '127.0.0.1',
27
+ ];
28
+ /** Check if a URL string points to an allowed domain. */
29
+ function isAllowedUrl(url) {
30
+ let hostname;
31
+ try {
32
+ hostname = new URL(url).hostname.toLowerCase();
33
+ }
34
+ catch {
35
+ return true; // can't parse — not a real URL, skip
36
+ }
37
+ for (const allowed of ALLOWED_DOMAINS) {
38
+ if (hostname === allowed || hostname.endsWith(`.${allowed}`))
39
+ return true;
40
+ }
41
+ return false;
42
+ }
43
+ function extOf(path) {
44
+ const dot = path.lastIndexOf('.');
45
+ const slash = path.lastIndexOf('/');
46
+ return dot > slash ? path.slice(dot).toLowerCase() : '';
47
+ }
48
+ export async function checkNoExternalFetch(source) {
49
+ const hits = [];
50
+ // Match fetch('https://...'), fetch("https://..."), fetch(`https://...`)
51
+ const fetchRe = /\bfetch\s*\(\s*['"`](https?:\/\/[^'"`\s)]+)/g;
52
+ // Match XMLHttpRequest .open() with external URLs
53
+ const xhrOpenRe = /\.open\s*\(\s*['"][A-Z]+['"]\s*,\s*['"`](https?:\/\/[^'"`\s)]+)/g;
54
+ // Match new XMLHttpRequest (just flag the presence together with open)
55
+ const xhrNewRe = /\bnew\s+XMLHttpRequest\b/;
56
+ for await (const path of source.list()) {
57
+ if (!path.startsWith('web/src/'))
58
+ continue;
59
+ if (!SCAN_EXTS.has(extOf(path)))
60
+ continue;
61
+ const raw = await source.read(path);
62
+ if (!raw)
63
+ continue;
64
+ // Strip comments but keep strings — URLs live in strings.
65
+ const content = stripCommentsOnly(raw);
66
+ for (const match of content.matchAll(fetchRe)) {
67
+ const url = match[1];
68
+ if (!isAllowedUrl(url)) {
69
+ hits.push({ file: path, url: url.length > 60 ? `${url.slice(0, 57)}...` : url });
70
+ }
71
+ }
72
+ // Only check XHR .open() calls if the file also creates an XMLHttpRequest.
73
+ if (xhrNewRe.test(content)) {
74
+ for (const match of content.matchAll(xhrOpenRe)) {
75
+ const url = match[1];
76
+ if (!isAllowedUrl(url)) {
77
+ hits.push({ file: path, url: url.length > 60 ? `${url.slice(0, 57)}...` : url });
78
+ }
79
+ }
80
+ }
81
+ }
82
+ if (hits.length === 0) {
83
+ return {
84
+ name: 'No external fetch',
85
+ status: 'pass',
86
+ detail: 'no fetch() or XMLHttpRequest calls to external domains in web/src/',
87
+ };
88
+ }
89
+ return {
90
+ name: 'No external fetch',
91
+ status: 'fail',
92
+ detail: `${hits.length} external fetch(es): ${hits
93
+ .slice(0, 3)
94
+ .map((h) => `${h.file} → ${h.url}`)
95
+ .join('; ')}${hits.length > 3 ? '...' : ''}`,
96
+ suggestions: [
97
+ 'Remove external API calls. Games must be self-contained and work offline.',
98
+ 'If the game needs server data, route it through the platform API (api.freegamestore.online).',
99
+ ],
100
+ };
101
+ }
102
+ //# sourceMappingURL=no-external-fetch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-external-fetch.js","sourceRoot":"","sources":["../../src/checks/no-external-fetch.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import type { FileSource } from '../lib/file-source.js';
2
+ import type { CheckResult } from '../types.js';
3
+ /**
4
+ * External scripts introduce supply-chain risk and can exfiltrate player
5
+ * data. Only platform-approved domains are allowed in `<script src>` tags
6
+ * inside `web/index.html`.
7
+ *
8
+ * Allowed: fonts.googleapis.com, fonts.gstatic.com,
9
+ * static.cloudflareinsights.com, freegamestore.online.
10
+ * Everything else fails.
11
+ *
12
+ * HTML comments are stripped first so `<!-- <script src="..."> -->` blocks
13
+ * don't trigger false positives.
14
+ */
15
+ export declare function checkNoExternalScripts(source: FileSource): Promise<CheckResult>;
16
+ //# sourceMappingURL=no-external-scripts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-external-scripts.d.ts","sourceRoot":"","sources":["../../src/checks/no-external-scripts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAExD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAa/C;;;;;;;;;;;GAWG;AACH,wBAAsB,sBAAsB,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC,CAqDrF"}
@@ -0,0 +1,91 @@
1
+ import { stripHtmlComments } from '../lib/strip.js';
2
+ const INDEX_HTML = 'web/index.html';
3
+ // Domains allowed in <script src="..."> tags. These are platform-owned
4
+ // or universally trusted CDNs that the storefront relies on.
5
+ const ALLOWED_DOMAINS = new Set([
6
+ 'fonts.googleapis.com',
7
+ 'fonts.gstatic.com',
8
+ 'static.cloudflareinsights.com',
9
+ 'freegamestore.online',
10
+ ]);
11
+ /**
12
+ * External scripts introduce supply-chain risk and can exfiltrate player
13
+ * data. Only platform-approved domains are allowed in `<script src>` tags
14
+ * inside `web/index.html`.
15
+ *
16
+ * Allowed: fonts.googleapis.com, fonts.gstatic.com,
17
+ * static.cloudflareinsights.com, freegamestore.online.
18
+ * Everything else fails.
19
+ *
20
+ * HTML comments are stripped first so `<!-- <script src="..."> -->` blocks
21
+ * don't trigger false positives.
22
+ */
23
+ export async function checkNoExternalScripts(source) {
24
+ const raw = await source.read(INDEX_HTML);
25
+ if (raw === null) {
26
+ return {
27
+ name: 'No external scripts',
28
+ status: 'pass',
29
+ detail: 'no web/index.html (not a web project)',
30
+ };
31
+ }
32
+ const html = stripHtmlComments(raw);
33
+ // Match <script ... src="..." ...> tags. The src value can use single
34
+ // or double quotes.
35
+ const scriptSrcRe = /<script\b[^>]*\bsrc\s*=\s*["']([^"']+)["'][^>]*>/gi;
36
+ const violations = [];
37
+ for (const match of html.matchAll(scriptSrcRe)) {
38
+ const src = match[1] ?? '';
39
+ // Relative or protocol-relative paths that don't point to an external
40
+ // domain are fine (local bundles, Vite-injected scripts, etc.).
41
+ if (!src.startsWith('http://') && !src.startsWith('https://') && !src.startsWith('//')) {
42
+ continue;
43
+ }
44
+ // Extract the hostname from the URL.
45
+ const hostname = extractHostname(src);
46
+ if (hostname === null)
47
+ continue;
48
+ // Check if the hostname (or any parent domain) is in the allow list.
49
+ if (isAllowed(hostname))
50
+ continue;
51
+ violations.push(src.length > 80 ? `${src.slice(0, 77)}...` : src);
52
+ }
53
+ if (violations.length === 0) {
54
+ return {
55
+ name: 'No external scripts',
56
+ status: 'pass',
57
+ detail: 'no disallowed external script sources in index.html',
58
+ };
59
+ }
60
+ return {
61
+ name: 'No external scripts',
62
+ status: 'fail',
63
+ detail: `${violations.length} external script(s) from disallowed domains: ${violations.slice(0, 3).join(', ')}${violations.length > 3 ? '...' : ''}`,
64
+ suggestions: [
65
+ 'Remove external <script src="..."> tags or self-host the scripts under web/public/.',
66
+ `Allowed domains: ${[...ALLOWED_DOMAINS].join(', ')}.`,
67
+ ],
68
+ };
69
+ }
70
+ function extractHostname(url) {
71
+ // Handle protocol-relative URLs (//example.com/...).
72
+ const cleaned = url.startsWith('//') ? `https:${url}` : url;
73
+ try {
74
+ return new URL(cleaned).hostname.toLowerCase();
75
+ }
76
+ catch {
77
+ return null;
78
+ }
79
+ }
80
+ /** Check if hostname or any parent domain matches the allow list. */
81
+ function isAllowed(hostname) {
82
+ if (ALLOWED_DOMAINS.has(hostname))
83
+ return true;
84
+ // Allow subdomains of allowed domains (e.g. api.freegamestore.online).
85
+ for (const allowed of ALLOWED_DOMAINS) {
86
+ if (hostname.endsWith(`.${allowed}`))
87
+ return true;
88
+ }
89
+ return false;
90
+ }
91
+ //# sourceMappingURL=no-external-scripts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-external-scripts.js","sourceRoot":"","sources":["../../src/checks/no-external-scripts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { FileSource } from '../lib/file-source.js';
2
+ import type { CheckResult } from '../types.js';
3
+ export declare function checkNoHardcodedColors(source: FileSource): Promise<CheckResult>;
4
+ //# sourceMappingURL=no-hardcoded-colors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-hardcoded-colors.d.ts","sourceRoot":"","sources":["../../src/checks/no-hardcoded-colors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAExD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAqC/C,wBAAsB,sBAAsB,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC,CAgDrF"}
@@ -0,0 +1,79 @@
1
+ import { stripCommentsOnly } from '../lib/strip.js';
2
+ /**
3
+ * Flags hardcoded hex color values in TSX files (React components).
4
+ * Games should use CSS custom properties (`var(--accent)`, `var(--ink)`,
5
+ * etc.) for UI chrome so the storefront can theme consistently and dark
6
+ * mode works out of the box.
7
+ *
8
+ * Only scans .tsx files — plain .ts files are likely canvas/game-engine
9
+ * logic where hardcoded colors for sprites, particles, and effects are
10
+ * expected and correct.
11
+ *
12
+ * Threshold: warn if total hex colors across all TSX files > 10.
13
+ *
14
+ * Strips comments and strings that are CSS variable definitions
15
+ * (like `--accent: #10b981`) before counting. The remaining hex values
16
+ * are likely inline styles or className-adjacent color specs that should
17
+ * use design tokens.
18
+ *
19
+ * WARN level — not a hard gate, but a strong signal the game isn't
20
+ * leveraging the design system.
21
+ */
22
+ const THRESHOLD = 10;
23
+ /** Match 6-digit or 3-digit hex colors: #rrggbb or #rgb. */
24
+ const HEX_COLOR_RE = /#(?:[0-9a-fA-F]{6}|[0-9a-fA-F]{3})\b/g;
25
+ /** Lines that define CSS custom properties — these are fine. */
26
+ const CSS_VAR_DEF_RE = /--[\w-]+\s*:\s*#/;
27
+ function extOf(path) {
28
+ const dot = path.lastIndexOf('.');
29
+ const slash = path.lastIndexOf('/');
30
+ return dot > slash ? path.slice(dot).toLowerCase() : '';
31
+ }
32
+ export async function checkNoHardcodedColors(source) {
33
+ let totalCount = 0;
34
+ const hitFiles = [];
35
+ for await (const path of source.list()) {
36
+ if (!path.startsWith('web/src/'))
37
+ continue;
38
+ if (extOf(path) !== '.tsx')
39
+ continue;
40
+ const raw = await source.read(path);
41
+ if (!raw)
42
+ continue;
43
+ // Strip comments but keep strings — hex colors in inline styles
44
+ // like style={{ color: '#ff0000' }} are the thing we're checking.
45
+ const stripped = stripCommentsOnly(raw);
46
+ // Count hex colors line by line, skipping CSS variable definitions.
47
+ let fileCount = 0;
48
+ for (const line of stripped.split('\n')) {
49
+ if (CSS_VAR_DEF_RE.test(line))
50
+ continue;
51
+ const matches = line.match(HEX_COLOR_RE);
52
+ if (matches)
53
+ fileCount += matches.length;
54
+ }
55
+ if (fileCount > 0) {
56
+ totalCount += fileCount;
57
+ hitFiles.push(path);
58
+ }
59
+ }
60
+ if (totalCount <= THRESHOLD) {
61
+ return {
62
+ name: 'No hardcoded colors',
63
+ status: 'pass',
64
+ detail: `${totalCount} hex color(s) in TSX files (threshold: ${THRESHOLD})`,
65
+ };
66
+ }
67
+ return {
68
+ name: 'No hardcoded colors',
69
+ status: 'warn',
70
+ detail: `${totalCount} hex color(s) across ${hitFiles.length} TSX file(s): ${hitFiles
71
+ .slice(0, 5)
72
+ .join(', ')}${hitFiles.length > 5 ? '...' : ''}`,
73
+ suggestions: [
74
+ 'Replace hardcoded hex colors with CSS custom properties: var(--accent), var(--ink), var(--surface), etc.',
75
+ 'Canvas drawing code belongs in .ts files (not .tsx) where hardcoded colors are expected.',
76
+ ],
77
+ };
78
+ }
79
+ //# sourceMappingURL=no-hardcoded-colors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-hardcoded-colors.js","sourceRoot":"","sources":["../../src/checks/no-hardcoded-colors.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAGpD;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,MAAM,SAAS,GAAG,EAAE,CAAC;AAErB,4DAA4D;AAC5D,MAAM,YAAY,GAAG,uCAAuC,CAAC;AAE7D,gEAAgE;AAChE,MAAM,cAAc,GAAG,kBAAkB,CAAC;AAE1C,SAAS,KAAK,CAAC,IAAY;IACzB,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAClC,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACpC,OAAO,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;AAC1D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAAC,MAAkB;IAC7D,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,MAAM,QAAQ,GAAa,EAAE,CAAC;IAE9B,IAAI,KAAK,EAAE,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC;QACvC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC;YAAE,SAAS;QAC3C,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,MAAM;YAAE,SAAS;QAErC,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpC,IAAI,CAAC,GAAG;YAAE,SAAS;QAEnB,gEAAgE;QAChE,kEAAkE;QAClE,MAAM,QAAQ,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC;QAExC,oEAAoE;QACpE,IAAI,SAAS,GAAG,CAAC,CAAC;QAClB,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YACxC,IAAI,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC;gBAAE,SAAS;YACxC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;YACzC,IAAI,OAAO;gBAAE,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC;QAC3C,CAAC;QAED,IAAI,SAAS,GAAG,CAAC,EAAE,CAAC;YAClB,UAAU,IAAI,SAAS,CAAC;YACxB,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtB,CAAC;IACH,CAAC;IAED,IAAI,UAAU,IAAI,SAAS,EAAE,CAAC;QAC5B,OAAO;YACL,IAAI,EAAE,qBAAqB;YAC3B,MAAM,EAAE,MAAM;YACd,MAAM,EAAE,GAAG,UAAU,0CAA0C,SAAS,GAAG;SAC5E,CAAC;IACJ,CAAC;IAED,OAAO;QACL,IAAI,EAAE,qBAAqB;QAC3B,MAAM,EAAE,MAAM;QACd,MAAM,EAAE,GAAG,UAAU,wBAAwB,QAAQ,CAAC,MAAM,iBAAiB,QAAQ;aAClF,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;aACX,IAAI,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE;QAClD,WAAW,EAAE;YACX,0GAA0G;YAC1G,0FAA0F;SAC3F;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,13 @@
1
+ import type { FileSource } from '../lib/file-source.js';
2
+ import type { CheckResult } from '../types.js';
3
+ /**
4
+ * Games on freegamestore.online must be free forever — no payment SDKs
5
+ * allowed. Scans source files for imports/usage of Stripe, PayPal,
6
+ * Braintree, Square, Paddle, LemonSqueezy, and RevenueCat.
7
+ *
8
+ * Uses comment-stripping (preserving string contents) so that real
9
+ * `import from "stripe"` is caught but a `// TODO: evaluate stripe`
10
+ * comment isn't.
11
+ */
12
+ export declare function checkNoPaymentSdk(source: FileSource): Promise<CheckResult>;
13
+ //# sourceMappingURL=no-payment-sdk.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-payment-sdk.d.ts","sourceRoot":"","sources":["../../src/checks/no-payment-sdk.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAExD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AA+E/C;;;;;;;;GAQG;AACH,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC,CAqChF"}
@@ -0,0 +1,118 @@
1
+ import { stripCommentsForExt } from '../lib/strip.js';
2
+ const PAYMENT_SDKS = [
3
+ {
4
+ name: 'stripe',
5
+ patterns: [
6
+ /@stripe\//i,
7
+ /stripe\.com/i,
8
+ /from\s+['"]stripe['"]/i,
9
+ /require\(['"]stripe['"]\)/i,
10
+ /\bStripe\s*\(/i,
11
+ /\bloadStripe\b/i,
12
+ ],
13
+ },
14
+ {
15
+ name: 'paypal',
16
+ patterns: [
17
+ /@paypal\//i,
18
+ /paypal\.com\/sdk/i,
19
+ /paypalobjects\.com/i,
20
+ /from\s+['"]@paypal\//i,
21
+ ],
22
+ },
23
+ {
24
+ name: 'braintree',
25
+ patterns: [
26
+ /braintree-web/i,
27
+ /braintreegateway/i,
28
+ /from\s+['"]braintree/i,
29
+ /require\(['"]braintree/i,
30
+ ],
31
+ },
32
+ {
33
+ name: 'square',
34
+ patterns: [
35
+ /@square\//i,
36
+ /squareup\.com/i,
37
+ /from\s+['"]square['"]/i,
38
+ /require\(['"]square['"]\)/i,
39
+ ],
40
+ },
41
+ {
42
+ name: 'paddle',
43
+ patterns: [
44
+ /@paddle\//i,
45
+ /paddle\.com/i,
46
+ /from\s+['"]@paddle\//i,
47
+ /\bPaddle\s*\.\s*(?:Setup|Checkout|Environment)\b/i,
48
+ ],
49
+ },
50
+ {
51
+ name: 'lemonsqueezy',
52
+ patterns: [
53
+ /@lemonsqueezy\//i,
54
+ /lemonsqueezy\.com/i,
55
+ /from\s+['"]@lemonsqueezy\//i,
56
+ ],
57
+ },
58
+ {
59
+ name: 'revenuecat',
60
+ patterns: [
61
+ /@revenuecat\//i,
62
+ /revenuecat\.com/i,
63
+ /from\s+['"]@revenuecat\//i,
64
+ /\bPurchases\s*\.\s*configure\b/i,
65
+ ],
66
+ },
67
+ ];
68
+ const SCAN_EXTS = new Set(['.ts', '.tsx', '.js', '.jsx', '.html', '.json']);
69
+ /**
70
+ * Games on freegamestore.online must be free forever — no payment SDKs
71
+ * allowed. Scans source files for imports/usage of Stripe, PayPal,
72
+ * Braintree, Square, Paddle, LemonSqueezy, and RevenueCat.
73
+ *
74
+ * Uses comment-stripping (preserving string contents) so that real
75
+ * `import from "stripe"` is caught but a `// TODO: evaluate stripe`
76
+ * comment isn't.
77
+ */
78
+ export async function checkNoPaymentSdk(source) {
79
+ const hits = [];
80
+ for await (const path of source.list()) {
81
+ const ext = extOf(path);
82
+ if (!SCAN_EXTS.has(ext))
83
+ continue;
84
+ const raw = await source.read(path);
85
+ if (!raw)
86
+ continue;
87
+ const content = stripCommentsForExt(raw, ext);
88
+ const matches = PAYMENT_SDKS.filter((s) => s.patterns.some((re) => re.test(content))).map((s) => s.name);
89
+ if (matches.length > 0) {
90
+ hits.push({ file: path, matches });
91
+ }
92
+ }
93
+ if (hits.length === 0) {
94
+ return {
95
+ name: 'No payment SDKs',
96
+ status: 'pass',
97
+ detail: 'no payment SDK imports found — game is free forever',
98
+ };
99
+ }
100
+ return {
101
+ name: 'No payment SDKs',
102
+ status: 'fail',
103
+ detail: `${hits.length} file(s) reference payment SDKs: ${hits
104
+ .slice(0, 3)
105
+ .map((h) => `${h.file} (${h.matches.join(', ')})`)
106
+ .join('; ')}${hits.length > 3 ? '...' : ''}`,
107
+ suggestions: [
108
+ 'Remove all payment SDK dependencies. Games on FreeGameStore must be 100% free — no in-app purchases, subscriptions, or payment flows.',
109
+ 'If you need monetisation, publish on ProGameStore (progamestore.online) instead.',
110
+ ],
111
+ };
112
+ }
113
+ function extOf(path) {
114
+ const dot = path.lastIndexOf('.');
115
+ const slash = path.lastIndexOf('/');
116
+ return dot > slash ? path.slice(dot).toLowerCase() : '';
117
+ }
118
+ //# sourceMappingURL=no-payment-sdk.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-payment-sdk.js","sourceRoot":"","sources":["../../src/checks/no-payment-sdk.ts"],"names":[],"mappings":"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"}
@@ -93,7 +93,7 @@ const FORBIDDEN_OVERFLOW = [
93
93
  /(?:^|[\s,{])(?:html|body)\s*\{[^}]*overflow-(?:x|y)\s*:\s*(?:scroll|auto)/im,
94
94
  ];
95
95
  const FORBIDDEN_MIN_HEIGHT = [/(?:^|[\s,{])(?:html|body)\s*\{[^}]*min-height\s*:\s*100vh/im];
96
- const VIEWPORT_LOCK = /(?:height|max-height)\s*:\s*100(?:s?vh)|GameShell|@freeappstore\/games/i;
96
+ const VIEWPORT_LOCK = /(?:height|max-height)\s*:\s*100(?:s?vh)|GameShell|@freegamestore\/games/i;
97
97
  function extOf(path) {
98
98
  const dot = path.lastIndexOf('.');
99
99
  const slash = path.lastIndexOf('/');
@@ -1 +1 @@
1
- {"version":3,"file":"no-scroll.js","sourceRoot":"","sources":["../../src/checks/no-scroll.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"no-scroll.js","sourceRoot":"","sources":["../../src/checks/no-scroll.ts"],"names":[],"mappings":"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"}
@@ -78,21 +78,21 @@ export async function checkNoTracking(source) {
78
78
  }
79
79
  if (hits.length === 0) {
80
80
  return {
81
- name: 'No tracking SDKs',
81
+ name: 'Analytics routed through platform loader',
82
82
  status: 'pass',
83
- detail: `scanned for ${TRACKERS.length} known trackers`,
83
+ detail: `no direct tracker SDKs found; analytics, if any, must flow through the platform loader (api.freegamestore.online/v1/analytics.js?app=<id>)`,
84
84
  };
85
85
  }
86
86
  return {
87
- name: 'No tracking SDKs',
87
+ name: 'Analytics routed through platform loader',
88
88
  status: 'fail',
89
- detail: `${hits.length} file(s) reference trackers: ${hits
89
+ detail: `${hits.length} file(s) install trackers directly: ${hits
90
90
  .slice(0, 3)
91
91
  .map((h) => `${h.file} (${h.matches.join(', ')})`)
92
92
  .join('; ')}${hits.length > 3 ? '…' : ''}`,
93
93
  suggestions: [
94
- 'FreeAppStore apps must be tracking-free. Remove the SDK + any analytics calls.',
95
- 'For private-by-design metrics, CF edge analytics already counts requests anonymously.',
94
+ 'Remove the direct SDK and reference the platform loader instead: <script src="https://api.freegamestore.online/v1/analytics.js?app=<id>" defer></script>.',
95
+ 'Configure providers (GA4, Plausible, custom <head>) via PUT /v1/apps/<id>/analytics — the loader emits the right tags so policy can evolve without redeploying every app.',
96
96
  ],
97
97
  };
98
98
  }
@@ -1 +1 @@
1
- {"version":3,"file":"no-tracking.js","sourceRoot":"","sources":["../../src/checks/no-tracking.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"no-tracking.js","sourceRoot":"","sources":["../../src/checks/no-tracking.ts"],"names":[],"mappings":"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"}