@fairfox/polly 0.18.0 → 0.20.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 +125 -948
- package/dist/cli/polly.js +25 -4
- package/dist/cli/polly.js.map +3 -3
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.js +46 -3
- package/dist/src/index.js.map +6 -5
- package/dist/src/shared/lib/resource.d.ts +54 -0
- package/dist/src/shared/lib/resource.js +583 -0
- package/dist/src/shared/lib/resource.js.map +13 -0
- package/dist/src/shared/lib/state.d.ts +1 -0
- package/dist/src/shared/lib/state.js +2 -1
- package/dist/src/shared/lib/state.js.map +3 -3
- package/dist/src/shared/state/app-state.js.map +2 -2
- package/dist/tools/init/templates/pwa/package.json.template +1 -2
- package/dist/tools/verify/specs/docker-compose.yml +1 -1
- package/dist/tools/verify/src/cli.js +269 -23
- package/dist/tools/verify/src/cli.js.map +6 -6
- package/dist/tools/visualize/src/cli.js +164 -8
- package/dist/tools/visualize/src/cli.js.map +3 -3
- package/package.json +5 -5
- package/dist/src/elysia/tla-generator.d.ts +0 -16
- package/dist/tools/verify/specs/verification.config.ts +0 -64
|
@@ -1784,12 +1784,13 @@ class HandlerExtractor {
|
|
|
1784
1784
|
const stateConstraints = [];
|
|
1785
1785
|
const globalStateConstraints = [];
|
|
1786
1786
|
const verifiedStates = [];
|
|
1787
|
+
const resources = [];
|
|
1787
1788
|
this.warnings = [];
|
|
1788
1789
|
const allSourceFiles = this.project.getSourceFiles();
|
|
1789
1790
|
const entryPoints = allSourceFiles.filter((f) => this.isWithinPackage(f.getFilePath()));
|
|
1790
1791
|
this.debugLogSourceFiles(allSourceFiles, entryPoints);
|
|
1791
1792
|
for (const entryPoint of entryPoints) {
|
|
1792
|
-
this.analyzeFileAndImports(entryPoint, handlers, messageTypes, invalidMessageTypes, stateConstraints, globalStateConstraints, verifiedStates);
|
|
1793
|
+
this.analyzeFileAndImports(entryPoint, handlers, messageTypes, invalidMessageTypes, stateConstraints, globalStateConstraints, verifiedStates, resources);
|
|
1793
1794
|
}
|
|
1794
1795
|
if (verifiedStates.length > 0) {
|
|
1795
1796
|
if (process.env["POLLY_DEBUG"]) {
|
|
@@ -1821,10 +1822,11 @@ class HandlerExtractor {
|
|
|
1821
1822
|
stateConstraints,
|
|
1822
1823
|
globalStateConstraints,
|
|
1823
1824
|
verifiedStates,
|
|
1825
|
+
resources,
|
|
1824
1826
|
warnings: this.warnings
|
|
1825
1827
|
};
|
|
1826
1828
|
}
|
|
1827
|
-
analyzeFileAndImports(sourceFile, handlers, messageTypes, invalidMessageTypes, stateConstraints, globalStateConstraints, verifiedStates) {
|
|
1829
|
+
analyzeFileAndImports(sourceFile, handlers, messageTypes, invalidMessageTypes, stateConstraints, globalStateConstraints, verifiedStates, resources) {
|
|
1828
1830
|
const filePath = sourceFile.getFilePath();
|
|
1829
1831
|
if (this.analyzedFiles.has(filePath)) {
|
|
1830
1832
|
return;
|
|
@@ -1842,6 +1844,20 @@ class HandlerExtractor {
|
|
|
1842
1844
|
globalStateConstraints.push(...fileGlobalConstraints);
|
|
1843
1845
|
const fileVerifiedStates = this.extractVerifiedStatesFromFile(sourceFile);
|
|
1844
1846
|
verifiedStates.push(...fileVerifiedStates);
|
|
1847
|
+
const fileResources = this.extractResourcesFromFile(sourceFile, filePath);
|
|
1848
|
+
for (const resource of fileResources) {
|
|
1849
|
+
resources.push(resource);
|
|
1850
|
+
const context = this.inferContext(filePath);
|
|
1851
|
+
const syntheticHandlers = this.createResourceHandlers(resource, context);
|
|
1852
|
+
for (const handler of syntheticHandlers) {
|
|
1853
|
+
handlers.push(handler);
|
|
1854
|
+
if (this.isValidTLAIdentifier(handler.messageType)) {
|
|
1855
|
+
messageTypes.add(handler.messageType);
|
|
1856
|
+
} else {
|
|
1857
|
+
invalidMessageTypes.add(handler.messageType);
|
|
1858
|
+
}
|
|
1859
|
+
}
|
|
1860
|
+
}
|
|
1845
1861
|
const importDeclarations = sourceFile.getImportDeclarations();
|
|
1846
1862
|
for (const importDecl of importDeclarations) {
|
|
1847
1863
|
const importedFile = importDecl.getModuleSpecifierSourceFile();
|
|
@@ -1853,7 +1869,7 @@ class HandlerExtractor {
|
|
|
1853
1869
|
}
|
|
1854
1870
|
continue;
|
|
1855
1871
|
}
|
|
1856
|
-
this.analyzeFileAndImports(importedFile, handlers, messageTypes, invalidMessageTypes, stateConstraints, globalStateConstraints, verifiedStates);
|
|
1872
|
+
this.analyzeFileAndImports(importedFile, handlers, messageTypes, invalidMessageTypes, stateConstraints, globalStateConstraints, verifiedStates, resources);
|
|
1857
1873
|
} else if (process.env["POLLY_DEBUG"]) {
|
|
1858
1874
|
const specifier = importDecl.getModuleSpecifierValue();
|
|
1859
1875
|
if (!specifier.startsWith("node:") && !this.isNodeModuleImport(specifier)) {
|
|
@@ -2212,7 +2228,9 @@ class HandlerExtractor {
|
|
|
2212
2228
|
return;
|
|
2213
2229
|
if (this.tryExtractSetConstructorPattern(fieldPath, right, assignments))
|
|
2214
2230
|
return;
|
|
2215
|
-
this.tryExtractMapConstructorPattern(fieldPath, right, assignments)
|
|
2231
|
+
if (this.tryExtractMapConstructorPattern(fieldPath, right, assignments))
|
|
2232
|
+
return;
|
|
2233
|
+
this.tryExtractSignalDirectValuePattern(fieldPath, right, assignments);
|
|
2216
2234
|
}
|
|
2217
2235
|
tryExtractStateFieldPattern(fieldPath, right, assignments) {
|
|
2218
2236
|
if (!fieldPath.startsWith("state."))
|
|
@@ -2331,6 +2349,25 @@ class HandlerExtractor {
|
|
|
2331
2349
|
}
|
|
2332
2350
|
return true;
|
|
2333
2351
|
}
|
|
2352
|
+
tryExtractSignalDirectValuePattern(fieldPath, right, assignments) {
|
|
2353
|
+
if (!fieldPath.endsWith(".value"))
|
|
2354
|
+
return false;
|
|
2355
|
+
const signalName = fieldPath.slice(0, -6);
|
|
2356
|
+
const literalValue = this.extractValue(right);
|
|
2357
|
+
if (literalValue !== undefined) {
|
|
2358
|
+
assignments.push({ field: signalName, value: literalValue });
|
|
2359
|
+
return true;
|
|
2360
|
+
}
|
|
2361
|
+
if (Node4.isPropertyAccessExpression(right)) {
|
|
2362
|
+
const rightPath = this.getPropertyPath(right);
|
|
2363
|
+
const parts = rightPath.split(".");
|
|
2364
|
+
if (parts.length === 2 && parts[0] !== undefined && parts[1] !== undefined && this.currentFunctionParams.includes(parts[0])) {
|
|
2365
|
+
assignments.push({ field: signalName, value: `param:${parts[1]}` });
|
|
2366
|
+
return true;
|
|
2367
|
+
}
|
|
2368
|
+
}
|
|
2369
|
+
return false;
|
|
2370
|
+
}
|
|
2334
2371
|
extractSetOperation(newExpr, fieldPath, signalName) {
|
|
2335
2372
|
const args = newExpr.getArguments();
|
|
2336
2373
|
if (args.length === 0) {
|
|
@@ -2447,11 +2484,11 @@ class HandlerExtractor {
|
|
|
2447
2484
|
return null;
|
|
2448
2485
|
switch (methodName) {
|
|
2449
2486
|
case "filter":
|
|
2450
|
-
return { field: signalName, value: "
|
|
2487
|
+
return { field: signalName, value: "NDET:FILTER" };
|
|
2451
2488
|
case "map":
|
|
2452
|
-
return { field: signalName, value: "
|
|
2489
|
+
return { field: signalName, value: "NDET:MAP" };
|
|
2453
2490
|
case "slice":
|
|
2454
|
-
return { field: signalName, value: "
|
|
2491
|
+
return { field: signalName, value: "NDET:FILTER" };
|
|
2455
2492
|
case "concat":
|
|
2456
2493
|
return { field: signalName, value: "@ \\o <<payload>>" };
|
|
2457
2494
|
case "reverse":
|
|
@@ -3722,6 +3759,125 @@ class HandlerExtractor {
|
|
|
3722
3759
|
}
|
|
3723
3760
|
return name || funcName;
|
|
3724
3761
|
}
|
|
3762
|
+
extractResourcesFromFile(sourceFile, filePath) {
|
|
3763
|
+
const resources = [];
|
|
3764
|
+
sourceFile.forEachDescendant((node) => {
|
|
3765
|
+
if (!Node4.isCallExpression(node))
|
|
3766
|
+
return;
|
|
3767
|
+
const resource = this.extractResourcePattern(node, filePath);
|
|
3768
|
+
if (resource) {
|
|
3769
|
+
resources.push(resource);
|
|
3770
|
+
}
|
|
3771
|
+
});
|
|
3772
|
+
return resources;
|
|
3773
|
+
}
|
|
3774
|
+
extractResourcePattern(node, filePath) {
|
|
3775
|
+
const expression = node.getExpression();
|
|
3776
|
+
if (!Node4.isIdentifier(expression))
|
|
3777
|
+
return null;
|
|
3778
|
+
if (expression.getText() !== "$resource")
|
|
3779
|
+
return null;
|
|
3780
|
+
const args = node.getArguments();
|
|
3781
|
+
if (args.length < 2)
|
|
3782
|
+
return null;
|
|
3783
|
+
const nameArg = args[0];
|
|
3784
|
+
if (!nameArg || !Node4.isStringLiteral(nameArg))
|
|
3785
|
+
return null;
|
|
3786
|
+
const name = nameArg.getLiteralValue();
|
|
3787
|
+
const optionsArg = args[1];
|
|
3788
|
+
if (!optionsArg || !Node4.isObjectLiteralExpression(optionsArg))
|
|
3789
|
+
return null;
|
|
3790
|
+
const sourceSignals = this.extractResourceSourceReads(optionsArg);
|
|
3791
|
+
const variableName = this.getVariableNameFromParent(node) || name;
|
|
3792
|
+
if (process.env["POLLY_DEBUG"]) {
|
|
3793
|
+
console.log(`[DEBUG] Found $resource: ${variableName} (name: "${name}") with source signals: [${sourceSignals.join(", ")}]`);
|
|
3794
|
+
}
|
|
3795
|
+
return {
|
|
3796
|
+
name,
|
|
3797
|
+
variableName,
|
|
3798
|
+
filePath,
|
|
3799
|
+
line: node.getStartLineNumber(),
|
|
3800
|
+
sourceSignals
|
|
3801
|
+
};
|
|
3802
|
+
}
|
|
3803
|
+
extractResourceSourceReads(optionsObj) {
|
|
3804
|
+
const signals = [];
|
|
3805
|
+
const sourceProp = optionsObj.getProperty("source");
|
|
3806
|
+
if (!sourceProp || !Node4.isPropertyAssignment(sourceProp))
|
|
3807
|
+
return signals;
|
|
3808
|
+
const sourceInit = sourceProp.getInitializer();
|
|
3809
|
+
if (!sourceInit)
|
|
3810
|
+
return signals;
|
|
3811
|
+
sourceInit.forEachDescendant((node) => {
|
|
3812
|
+
if (!Node4.isPropertyAccessExpression(node))
|
|
3813
|
+
return;
|
|
3814
|
+
const text = node.getText();
|
|
3815
|
+
const match = text.match(/^(\w+)\.value(?:\.(\w+))?$/);
|
|
3816
|
+
if (match) {
|
|
3817
|
+
const signalName = match[1];
|
|
3818
|
+
const fieldName = match[2];
|
|
3819
|
+
if (fieldName) {
|
|
3820
|
+
signals.push(`${signalName}_${fieldName}`);
|
|
3821
|
+
} else {
|
|
3822
|
+
signals.push(signalName);
|
|
3823
|
+
}
|
|
3824
|
+
}
|
|
3825
|
+
});
|
|
3826
|
+
return signals;
|
|
3827
|
+
}
|
|
3828
|
+
createResourceHandlers(resource, context) {
|
|
3829
|
+
const { name, filePath, line } = resource;
|
|
3830
|
+
const location = { file: filePath, line };
|
|
3831
|
+
const fetchStart = {
|
|
3832
|
+
messageType: `${name}_FetchStart`,
|
|
3833
|
+
node: context,
|
|
3834
|
+
assignments: [
|
|
3835
|
+
{ field: `${name}_status`, value: "loading" },
|
|
3836
|
+
{ field: `${name}_error`, value: false }
|
|
3837
|
+
],
|
|
3838
|
+
preconditions: [
|
|
3839
|
+
{
|
|
3840
|
+
expression: `${name}_status !== "loading"`,
|
|
3841
|
+
location: { line, column: 0 }
|
|
3842
|
+
}
|
|
3843
|
+
],
|
|
3844
|
+
postconditions: [],
|
|
3845
|
+
location
|
|
3846
|
+
};
|
|
3847
|
+
const fetchSuccess = {
|
|
3848
|
+
messageType: `${name}_FetchSuccess`,
|
|
3849
|
+
node: context,
|
|
3850
|
+
assignments: [
|
|
3851
|
+
{ field: `${name}_status`, value: "success" },
|
|
3852
|
+
{ field: `${name}_error`, value: false }
|
|
3853
|
+
],
|
|
3854
|
+
preconditions: [
|
|
3855
|
+
{
|
|
3856
|
+
expression: `${name}_status === "loading"`,
|
|
3857
|
+
location: { line, column: 0 }
|
|
3858
|
+
}
|
|
3859
|
+
],
|
|
3860
|
+
postconditions: [],
|
|
3861
|
+
location
|
|
3862
|
+
};
|
|
3863
|
+
const fetchError = {
|
|
3864
|
+
messageType: `${name}_FetchError`,
|
|
3865
|
+
node: context,
|
|
3866
|
+
assignments: [
|
|
3867
|
+
{ field: `${name}_status`, value: "error" },
|
|
3868
|
+
{ field: `${name}_error`, value: true }
|
|
3869
|
+
],
|
|
3870
|
+
preconditions: [
|
|
3871
|
+
{
|
|
3872
|
+
expression: `${name}_status === "loading"`,
|
|
3873
|
+
location: { line, column: 0 }
|
|
3874
|
+
}
|
|
3875
|
+
],
|
|
3876
|
+
postconditions: [],
|
|
3877
|
+
location
|
|
3878
|
+
};
|
|
3879
|
+
return [fetchStart, fetchSuccess, fetchError];
|
|
3880
|
+
}
|
|
3725
3881
|
}
|
|
3726
3882
|
|
|
3727
3883
|
// tools/analysis/src/extract/integrations.ts
|
|
@@ -6052,4 +6208,4 @@ main().catch((_error) => {
|
|
|
6052
6208
|
process.exit(1);
|
|
6053
6209
|
});
|
|
6054
6210
|
|
|
6055
|
-
//# debugId=
|
|
6211
|
+
//# debugId=877A170E241AB38F64756E2164756E21
|