@freegamestore/compliance 0.7.0 → 0.8.0
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.
- package/README.md +1 -1
- package/dist/checks/deploy-workflow.d.ts +16 -0
- package/dist/checks/deploy-workflow.d.ts.map +1 -0
- package/dist/checks/deploy-workflow.js +33 -0
- package/dist/checks/deploy-workflow.js.map +1 -0
- package/dist/checks/game-naming.d.ts +4 -0
- package/dist/checks/game-naming.d.ts.map +1 -0
- package/dist/checks/game-naming.js +98 -0
- package/dist/checks/game-naming.js.map +1 -0
- package/dist/checks/gitignore-complete.d.ts +4 -0
- package/dist/checks/gitignore-complete.d.ts.map +1 -0
- package/dist/checks/gitignore-complete.js +51 -0
- package/dist/checks/gitignore-complete.js.map +1 -0
- package/dist/checks/no-any-types.d.ts +4 -0
- package/dist/checks/no-any-types.d.ts.map +1 -0
- package/dist/checks/no-any-types.js +72 -0
- package/dist/checks/no-any-types.js.map +1 -0
- package/dist/checks/no-console-log.d.ts +4 -0
- package/dist/checks/no-console-log.d.ts.map +1 -0
- package/dist/checks/no-console-log.js +63 -0
- package/dist/checks/no-console-log.js.map +1 -0
- package/dist/checks/no-cookies.d.ts +13 -0
- package/dist/checks/no-cookies.d.ts.map +1 -0
- package/dist/checks/no-cookies.js +64 -0
- package/dist/checks/no-cookies.js.map +1 -0
- package/dist/checks/no-excessive-inline-styles.d.ts +4 -0
- package/dist/checks/no-excessive-inline-styles.d.ts.map +1 -0
- package/dist/checks/no-excessive-inline-styles.js +82 -0
- package/dist/checks/no-excessive-inline-styles.js.map +1 -0
- package/dist/checks/no-external-fetch.d.ts +4 -0
- package/dist/checks/no-external-fetch.d.ts.map +1 -0
- package/dist/checks/no-external-fetch.js +102 -0
- package/dist/checks/no-external-fetch.js.map +1 -0
- package/dist/checks/no-external-scripts.d.ts +16 -0
- package/dist/checks/no-external-scripts.d.ts.map +1 -0
- package/dist/checks/no-external-scripts.js +91 -0
- package/dist/checks/no-external-scripts.js.map +1 -0
- package/dist/checks/no-hardcoded-colors.d.ts +4 -0
- package/dist/checks/no-hardcoded-colors.d.ts.map +1 -0
- package/dist/checks/no-hardcoded-colors.js +79 -0
- package/dist/checks/no-hardcoded-colors.js.map +1 -0
- package/dist/checks/no-payment-sdk.d.ts +13 -0
- package/dist/checks/no-payment-sdk.d.ts.map +1 -0
- package/dist/checks/no-payment-sdk.js +118 -0
- package/dist/checks/no-payment-sdk.js.map +1 -0
- package/dist/checks/no-scroll.js +1 -1
- package/dist/checks/no-scroll.js.map +1 -1
- package/dist/checks/no-tracking.js +6 -6
- package/dist/checks/no-tracking.js.map +1 -1
- package/dist/checks/pwa-icons.d.ts +15 -0
- package/dist/checks/pwa-icons.d.ts.map +1 -0
- package/dist/checks/pwa-icons.js +38 -0
- package/dist/checks/pwa-icons.js.map +1 -0
- package/dist/checks/react-strict-mode.d.ts +4 -0
- package/dist/checks/react-strict-mode.d.ts.map +1 -0
- package/dist/checks/react-strict-mode.js +43 -0
- package/dist/checks/react-strict-mode.js.map +1 -0
- package/dist/checks/sdk-version.d.ts +4 -0
- package/dist/checks/sdk-version.d.ts.map +1 -0
- package/dist/checks/sdk-version.js +80 -0
- package/dist/checks/sdk-version.js.map +1 -0
- package/dist/checks/tech-versions.d.ts +4 -0
- package/dist/checks/tech-versions.d.ts.map +1 -0
- package/dist/checks/tech-versions.js +100 -0
- package/dist/checks/tech-versions.js.map +1 -0
- package/dist/checks/typescript-strict.d.ts +14 -0
- package/dist/checks/typescript-strict.d.ts.map +1 -0
- package/dist/checks/typescript-strict.js +155 -0
- package/dist/checks/typescript-strict.js.map +1 -0
- package/dist/checks/uses-game-sdk.d.ts +16 -0
- package/dist/checks/uses-game-sdk.d.ts.map +1 -0
- package/dist/checks/uses-game-sdk.js +82 -0
- package/dist/checks/uses-game-sdk.js.map +1 -0
- package/dist/checks/uses-localstorage.d.ts +14 -0
- package/dist/checks/uses-localstorage.d.ts.map +1 -0
- package/dist/checks/uses-localstorage.js +45 -0
- package/dist/checks/uses-localstorage.js.map +1 -0
- package/dist/index.d.ts +19 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +44 -2
- package/dist/index.js.map +1 -1
- package/dist/lib/strip.js +4 -3
- package/dist/lib/strip.js.map +1 -1
- package/dist/live/index.d.ts.map +1 -1
- package/dist/live/index.js +9 -4
- package/dist/live/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -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 @@
|
|
|
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":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAWtD,MAAM,YAAY,GAAkB;IAClC;QACE,IAAI,EAAE,QAAQ;QACd,QAAQ,EAAE;YACR,YAAY;YACZ,cAAc;YACd,wBAAwB;YACxB,4BAA4B;YAC5B,gBAAgB;YAChB,iBAAiB;SAClB;KACF;IACD;QACE,IAAI,EAAE,QAAQ;QACd,QAAQ,EAAE;YACR,YAAY;YACZ,mBAAmB;YACnB,qBAAqB;YACrB,uBAAuB;SACxB;KACF;IACD;QACE,IAAI,EAAE,WAAW;QACjB,QAAQ,EAAE;YACR,gBAAgB;YAChB,mBAAmB;YACnB,uBAAuB;YACvB,yBAAyB;SAC1B;KACF;IACD;QACE,IAAI,EAAE,QAAQ;QACd,QAAQ,EAAE;YACR,YAAY;YACZ,gBAAgB;YAChB,wBAAwB;YACxB,4BAA4B;SAC7B;KACF;IACD;QACE,IAAI,EAAE,QAAQ;QACd,QAAQ,EAAE;YACR,YAAY;YACZ,cAAc;YACd,uBAAuB;YACvB,mDAAmD;SACpD;KACF;IACD;QACE,IAAI,EAAE,cAAc;QACpB,QAAQ,EAAE;YACR,kBAAkB;YAClB,oBAAoB;YACpB,6BAA6B;SAC9B;KACF;IACD;QACE,IAAI,EAAE,YAAY;QAClB,QAAQ,EAAE;YACR,gBAAgB;YAChB,kBAAkB;YAClB,2BAA2B;YAC3B,iCAAiC;SAClC;KACF;CACF,CAAC;AAEF,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;AAE5E;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,MAAkB;IACxD,MAAM,IAAI,GAA0C,EAAE,CAAC;IAEvD,IAAI,KAAK,EAAE,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC;QACvC,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;QACxB,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,SAAS;QAClC,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpC,IAAI,CAAC,GAAG;YAAE,SAAS;QACnB,MAAM,OAAO,GAAG,mBAAmB,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QAC9C,MAAM,OAAO,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,CACvF,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CACd,CAAC;QACF,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvB,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;QACrC,CAAC;IACH,CAAC;IAED,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,OAAO;YACL,IAAI,EAAE,iBAAiB;YACvB,MAAM,EAAE,MAAM;YACd,MAAM,EAAE,qDAAqD;SAC9D,CAAC;IACJ,CAAC;IAED,OAAO;QACL,IAAI,EAAE,iBAAiB;QACvB,MAAM,EAAE,MAAM;QACd,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,oCAAoC,IAAI;aAC3D,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;aACX,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;aACjD,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE;QAC9C,WAAW,EAAE;YACX,uIAAuI;YACvI,kFAAkF;SACnF;KACF,CAAC;AACJ,CAAC;AAED,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"}
|
package/dist/checks/no-scroll.js
CHANGED
|
@@ -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|@
|
|
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: '
|
|
81
|
+
name: 'Analytics routed through platform loader',
|
|
82
82
|
status: 'pass',
|
|
83
|
-
detail: `
|
|
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: '
|
|
87
|
+
name: 'Analytics routed through platform loader',
|
|
88
88
|
status: 'fail',
|
|
89
|
-
detail: `${hits.length} file(s)
|
|
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
|
-
'
|
|
95
|
-
'
|
|
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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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { FileSource } from '../lib/file-source.js';
|
|
2
|
+
import type { CheckResult } from '../types.js';
|
|
3
|
+
/**
|
|
4
|
+
* PWA installability requires a 192x192 and a 512x512 icon. The
|
|
5
|
+
* platform manifest template references `icon-192.png` and
|
|
6
|
+
* `icon-512.png` in `web/public/`. Both must exist for the game to be
|
|
7
|
+
* installable on all devices.
|
|
8
|
+
*
|
|
9
|
+
* This check verifies file existence only — it doesn't validate
|
|
10
|
+
* dimensions (that would require image decoding). The naming convention
|
|
11
|
+
* makes the intent clear enough that a mis-sized file is caught by
|
|
12
|
+
* Lighthouse at deploy time.
|
|
13
|
+
*/
|
|
14
|
+
export declare function checkPwaIcons(source: FileSource): Promise<CheckResult>;
|
|
15
|
+
//# sourceMappingURL=pwa-icons.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pwa-icons.d.ts","sourceRoot":"","sources":["../../src/checks/pwa-icons.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAI/C;;;;;;;;;;GAUG;AACH,wBAAsB,aAAa,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC,CA2B5E"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
const REQUIRED_ICONS = ['web/public/icon-192.png', 'web/public/icon-512.png'];
|
|
2
|
+
/**
|
|
3
|
+
* PWA installability requires a 192x192 and a 512x512 icon. The
|
|
4
|
+
* platform manifest template references `icon-192.png` and
|
|
5
|
+
* `icon-512.png` in `web/public/`. Both must exist for the game to be
|
|
6
|
+
* installable on all devices.
|
|
7
|
+
*
|
|
8
|
+
* This check verifies file existence only — it doesn't validate
|
|
9
|
+
* dimensions (that would require image decoding). The naming convention
|
|
10
|
+
* makes the intent clear enough that a mis-sized file is caught by
|
|
11
|
+
* Lighthouse at deploy time.
|
|
12
|
+
*/
|
|
13
|
+
export async function checkPwaIcons(source) {
|
|
14
|
+
const missing = [];
|
|
15
|
+
for (const iconPath of REQUIRED_ICONS) {
|
|
16
|
+
const content = await source.read(iconPath);
|
|
17
|
+
if (content === null) {
|
|
18
|
+
missing.push(iconPath);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
if (missing.length === 0) {
|
|
22
|
+
return {
|
|
23
|
+
name: 'PWA icons',
|
|
24
|
+
status: 'pass',
|
|
25
|
+
detail: 'icon-192.png and icon-512.png present in web/public/',
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
return {
|
|
29
|
+
name: 'PWA icons',
|
|
30
|
+
status: 'fail',
|
|
31
|
+
detail: `missing PWA icon(s): ${missing.join(', ')}`,
|
|
32
|
+
suggestions: [
|
|
33
|
+
'Add the missing icon file(s) to web/public/. Both icon-192.png (192x192) and icon-512.png (512x512) are required for PWA installability.',
|
|
34
|
+
'Use a square PNG with your game logo on a solid background. Tools like https://realfavicongenerator.net/ can generate both sizes.',
|
|
35
|
+
],
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=pwa-icons.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pwa-icons.js","sourceRoot":"","sources":["../../src/checks/pwa-icons.ts"],"names":[],"mappings":"AAGA,MAAM,cAAc,GAAG,CAAC,yBAAyB,EAAE,yBAAyB,CAAU,CAAC;AAEvF;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,MAAkB;IACpD,MAAM,OAAO,GAAa,EAAE,CAAC;IAE7B,KAAK,MAAM,QAAQ,IAAI,cAAc,EAAE,CAAC;QACtC,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC5C,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;YACrB,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACzB,CAAC;IACH,CAAC;IAED,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO;YACL,IAAI,EAAE,WAAW;YACjB,MAAM,EAAE,MAAM;YACd,MAAM,EAAE,sDAAsD;SAC/D,CAAC;IACJ,CAAC;IAED,OAAO;QACL,IAAI,EAAE,WAAW;QACjB,MAAM,EAAE,MAAM;QACd,MAAM,EAAE,wBAAwB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;QACpD,WAAW,EAAE;YACX,0IAA0I;YAC1I,mIAAmI;SACpI;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"react-strict-mode.d.ts","sourceRoot":"","sources":["../../src/checks/react-strict-mode.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAkB/C,wBAAsB,oBAAoB,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC,CA8BnF"}
|