@produtype/core 0.83.1 → 0.84.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.
|
@@ -102,6 +102,14 @@ async function detectEngine(ctx) {
|
|
|
102
102
|
evidence.push({ type: 'note', value: `asset pipeline script "${name}"` });
|
|
103
103
|
}
|
|
104
104
|
const conclusive = engineDeps.length > 0 || engineFiles.length > 0;
|
|
105
|
+
/**
|
|
106
|
+
* Whether the game ships as a binary rather than as a page.
|
|
107
|
+
*
|
|
108
|
+
* `ENGINE_FILES` are the project files of engines that build an executable — Godot,
|
|
109
|
+
* Unreal, Unity, LÖVE — and `ENGINE_DEPS` are the ones that run in a browser. The
|
|
110
|
+
* difference decides whether questions about HTTP caching mean anything here at all.
|
|
111
|
+
*/
|
|
112
|
+
const nativeEngine = engineFiles.length > 0 && engineDeps.length === 0;
|
|
105
113
|
/**
|
|
106
114
|
* How much a project looks like a game without proving it.
|
|
107
115
|
*
|
|
@@ -124,6 +132,7 @@ async function detectEngine(ctx) {
|
|
|
124
132
|
details: {
|
|
125
133
|
engines: engineDeps,
|
|
126
134
|
engineFiles,
|
|
135
|
+
nativeEngine,
|
|
127
136
|
supporting,
|
|
128
137
|
frameLoop: loops.length > 0,
|
|
129
138
|
realtime,
|
|
@@ -171,7 +180,25 @@ async function detectStatePersistence(ctx) {
|
|
|
171
180
|
* memory, written nowhere, gone when the operating system reclaims the process.
|
|
172
181
|
*/
|
|
173
182
|
const deviceStore = await (0, localStores_1.readLocalStores)(ctx, 3);
|
|
174
|
-
|
|
183
|
+
/**
|
|
184
|
+
* Where a game that is not in a browser writes a save.
|
|
185
|
+
*
|
|
186
|
+
* `localStorage` is the browser's, and the engines each have their own: `PlayerPrefs`
|
|
187
|
+
* and `Application.persistentDataPath` are Unity's, `love.filesystem` is LÖVE's,
|
|
188
|
+
* `FileAccess` and `ConfigFile` are Godot's. Every one is the name its engine
|
|
189
|
+
* defines, so a call to it is the capability rather than a word that tends to
|
|
190
|
+
* accompany it.
|
|
191
|
+
*/
|
|
192
|
+
const engineSaves = await (0, textSearch_1.searchInFiles)(ctx.root, ctx.files.source, [
|
|
193
|
+
/PlayerPrefs\s*\.\s*(Set|Get)/,
|
|
194
|
+
/Application\s*\.\s*persistentDataPath/,
|
|
195
|
+
/love\s*\.\s*filesystem\s*\.\s*(write|read|newFile)/,
|
|
196
|
+
/\bConfigFile\s*\.\s*new\s*\(|\bFileAccess\s*\.\s*open\s*\(/,
|
|
197
|
+
], 3);
|
|
198
|
+
for (const hit of engineSaves) {
|
|
199
|
+
evidence.push({ type: 'snippet', value: hit.snippet, file: hit.file, line: hit.line });
|
|
200
|
+
}
|
|
201
|
+
const onDevice = deviceStore.dependencies.length > 0 || deviceStore.uses.length > 0 || engineSaves.length > 0;
|
|
175
202
|
const durable = serverStore || onDevice;
|
|
176
203
|
if (serverStore)
|
|
177
204
|
evidence.push({ type: 'note', value: 'a durable store is present' });
|
|
@@ -211,6 +211,24 @@ function deriveStatus(analysis, capability) {
|
|
|
211
211
|
return 'partial';
|
|
212
212
|
return 'missing';
|
|
213
213
|
}
|
|
214
|
+
/**
|
|
215
|
+
* A question about HTTP caching, asked of a game that ships as a binary.
|
|
216
|
+
*
|
|
217
|
+
* `Cache-Control`, `_headers` and `vercel.json` are how a browser is told to keep
|
|
218
|
+
* the assets, and every one of the five game fixtures — Unity, LÖVE and three web
|
|
219
|
+
* ones alike — was told at `high` that it has none. For the native two there is no
|
|
220
|
+
* browser to tell: the assets are inside the executable the player downloaded
|
|
221
|
+
* once. The capability is written for one delivery medium and was required of
|
|
222
|
+
* both.
|
|
223
|
+
*
|
|
224
|
+
* `not_applicable` rather than `unknown`: this is not a question that went
|
|
225
|
+
* unasked, it is one that does not arise.
|
|
226
|
+
*/
|
|
227
|
+
case 'app.asset-delivery': {
|
|
228
|
+
if (detector(analysis, 'game.engine')?.details?.nativeEngine === true)
|
|
229
|
+
return 'not_applicable';
|
|
230
|
+
return detector(analysis, 'app.assetDelivery')?.present ? 'present' : 'missing';
|
|
231
|
+
}
|
|
214
232
|
case 'jobs.background': {
|
|
215
233
|
return detector(analysis, 'jobs.background')?.present ? 'present' : 'missing';
|
|
216
234
|
}
|
package/dist/report/types.d.ts
CHANGED
|
@@ -114,6 +114,19 @@ export interface ProductionReadinessReport {
|
|
|
114
114
|
findingsByCategory: Record<Category, Finding[]>;
|
|
115
115
|
criticalIssues: Finding[];
|
|
116
116
|
warnings: Finding[];
|
|
117
|
+
/**
|
|
118
|
+
* The observed rules that passed. Not the capabilities a profile asked for and found.
|
|
119
|
+
*
|
|
120
|
+
* Those live in `productProfile.capabilities`, every one of them, with its own
|
|
121
|
+
* status — and they are deliberately not repeated here. A met expectation and the
|
|
122
|
+
* observed rule underneath it are the same verification stated twice: counting both
|
|
123
|
+
* made "basic web security: 4 checks verified" read as 7.
|
|
124
|
+
*
|
|
125
|
+
* Written down because the shape misleads on the way in. Reading `findings` and
|
|
126
|
+
* `passedChecks` and finding no capability in either looks exactly like a capability
|
|
127
|
+
* no project ever satisfies, and it is not: it is the wrong array. That reading was
|
|
128
|
+
* made twice while surveying this analyzer's own corpus.
|
|
129
|
+
*/
|
|
117
130
|
passedChecks: Finding[];
|
|
118
131
|
suggestedNextSteps: string[];
|
|
119
132
|
technicalEvidence: Array<{
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@produtype/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.84.1",
|
|
4
4
|
"description": "Deterministic CLI and library that analyzes a web application repository and reports how far it is from production-ready for the kind of product it is meant to be.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"bin": {
|