@fairfox/polly 0.12.3 → 0.13.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.
Files changed (36) hide show
  1. package/dist/src/background/index.js +118 -1
  2. package/dist/src/background/index.js.map +5 -4
  3. package/dist/src/background/message-router.js +118 -1
  4. package/dist/src/background/message-router.js.map +5 -4
  5. package/dist/src/index.d.ts +2 -0
  6. package/dist/src/index.js +203 -3
  7. package/dist/src/index.js.map +9 -6
  8. package/dist/src/shared/lib/constraints.d.ts +61 -0
  9. package/dist/src/shared/lib/context-helpers.js +118 -1
  10. package/dist/src/shared/lib/context-helpers.js.map +5 -4
  11. package/dist/src/shared/lib/message-bus.d.ts +22 -0
  12. package/dist/src/shared/lib/message-bus.js +118 -1
  13. package/dist/src/shared/lib/message-bus.js.map +5 -4
  14. package/dist/src/shared/lib/state.d.ts +8 -2
  15. package/dist/src/shared/lib/state.js +140 -3
  16. package/dist/src/shared/lib/state.js.map +6 -5
  17. package/dist/src/shared/lib/validation.d.ts +94 -0
  18. package/dist/src/shared/state/app-state.d.ts +4 -1
  19. package/dist/src/shared/state/app-state.js +140 -3
  20. package/dist/src/shared/state/app-state.js.map +6 -5
  21. package/dist/tools/analysis/src/extract/handlers.d.ts +24 -2
  22. package/dist/tools/teach/src/cli.js +102 -17
  23. package/dist/tools/teach/src/cli.js.map +3 -3
  24. package/dist/tools/teach/src/index.js +102 -17
  25. package/dist/tools/teach/src/index.js.map +3 -3
  26. package/dist/tools/verify/Dockerfile +11 -7
  27. package/dist/tools/verify/specs/Dockerfile +21 -5
  28. package/dist/tools/verify/specs/README.md +13 -6
  29. package/dist/tools/verify/src/cli.js +102 -17
  30. package/dist/tools/verify/src/cli.js.map +3 -3
  31. package/dist/tools/verify/src/config.js +8 -2
  32. package/dist/tools/verify/src/config.js.map +3 -3
  33. package/dist/tools/verify/src/primitives/index.d.ts +21 -8
  34. package/dist/tools/visualize/src/cli.js +102 -17
  35. package/dist/tools/visualize/src/cli.js.map +3 -3
  36. package/package.json +1 -1
package/dist/src/index.js CHANGED
@@ -48,6 +48,90 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
48
48
  throw Error('Dynamic require of "' + x + '" is not supported');
49
49
  });
50
50
 
51
+ // src/shared/lib/constraints.ts
52
+ var exports_constraints = {};
53
+ __export(exports_constraints, {
54
+ registerConstraints: () => registerConstraints,
55
+ registerConstraint: () => registerConstraint,
56
+ isRuntimeConstraintsEnabled: () => isRuntimeConstraintsEnabled,
57
+ getRegisteredConstraints: () => getRegisteredConstraints,
58
+ clearConstraints: () => clearConstraints,
59
+ checkPreconditions: () => checkPreconditions,
60
+ checkPostconditions: () => checkPostconditions
61
+ });
62
+ function registerConstraint(field, messageType, constraint) {
63
+ if (!registry.has(field)) {
64
+ registry.set(field, new Map);
65
+ }
66
+ registry.get(field)?.set(messageType, constraint);
67
+ }
68
+ function registerConstraints(field, constraints) {
69
+ for (const [messageType, constraint] of Object.entries(constraints)) {
70
+ const runtimeConstraint = {
71
+ message: constraint.message
72
+ };
73
+ if (typeof constraint.requires === "function") {
74
+ runtimeConstraint.requires = constraint.requires;
75
+ }
76
+ if (typeof constraint.ensures === "function") {
77
+ runtimeConstraint.ensures = constraint.ensures;
78
+ }
79
+ if (runtimeConstraint.requires || runtimeConstraint.ensures) {
80
+ registerConstraint(field, messageType, runtimeConstraint);
81
+ }
82
+ }
83
+ }
84
+ function executeConstraint(predicate, state, messageType, field, customMessage, constraintType = "Precondition") {
85
+ try {
86
+ const result = predicate(state);
87
+ if (!result) {
88
+ const message = customMessage || `${constraintType} failed for ${messageType} on field ${field}`;
89
+ throw new Error(message);
90
+ }
91
+ } catch (error) {
92
+ if (error instanceof Error && error.message.includes(`${constraintType} failed`)) {
93
+ throw error;
94
+ }
95
+ const message = customMessage || `${constraintType} check error for ${messageType} on field ${field}`;
96
+ throw new Error(`${message}: ${error}`);
97
+ }
98
+ }
99
+ function checkPreconditions(messageType, state) {
100
+ for (const [field, constraints] of registry) {
101
+ const constraint = constraints.get(messageType);
102
+ if (constraint?.requires) {
103
+ executeConstraint(constraint.requires, state, messageType, field, constraint.message, "Precondition");
104
+ }
105
+ }
106
+ }
107
+ function checkPostconditions(messageType, state) {
108
+ for (const [field, constraints] of registry) {
109
+ const constraint = constraints.get(messageType);
110
+ if (constraint?.ensures) {
111
+ executeConstraint(constraint.ensures, state, messageType, field, constraint.message, "Postcondition");
112
+ }
113
+ }
114
+ }
115
+ function clearConstraints() {
116
+ registry.clear();
117
+ }
118
+ function getRegisteredConstraints() {
119
+ return new Map(registry);
120
+ }
121
+ function isRuntimeConstraintsEnabled() {
122
+ if (typeof process !== "undefined" && process.env) {
123
+ return process.env["POLLY_RUNTIME_CONSTRAINTS"] === "true";
124
+ }
125
+ if (typeof Bun !== "undefined" && Bun.env) {
126
+ return Bun.env["POLLY_RUNTIME_CONSTRAINTS"] === "true";
127
+ }
128
+ return false;
129
+ }
130
+ var registry;
131
+ var init_constraints = __esm(() => {
132
+ registry = new Map;
133
+ });
134
+
51
135
  // src/shared/adapters/chrome/context-menus.chrome.ts
52
136
  class ChromeContextMenusAdapter {
53
137
  async create(createProperties) {
@@ -724,6 +808,7 @@ class MessageBus {
724
808
  port = null;
725
809
  errorHandler;
726
810
  userErrorHandlers = [];
811
+ stateAccessor = null;
727
812
  messageListener = null;
728
813
  constructor(context, adapters, options) {
729
814
  this.context = context;
@@ -811,6 +896,9 @@ class MessageBus {
811
896
  onError(handler) {
812
897
  this.userErrorHandlers.push(handler);
813
898
  }
899
+ setStateAccessor(accessor) {
900
+ this.stateAccessor = accessor;
901
+ }
814
902
  async sendToBackground(payload, options) {
815
903
  return this.send(payload, { ...options, target: "background" });
816
904
  }
@@ -968,11 +1056,40 @@ class MessageBus {
968
1056
  }
969
1057
  try {
970
1058
  globalExecutionTracker.track(message.id, message.payload.type);
1059
+ if (this.stateAccessor) {
1060
+ try {
1061
+ const { checkPreconditions: checkPreconditions2, isRuntimeConstraintsEnabled: isRuntimeConstraintsEnabled2 } = await Promise.resolve().then(() => (init_constraints(), exports_constraints));
1062
+ if (isRuntimeConstraintsEnabled2()) {
1063
+ const currentState = this.stateAccessor();
1064
+ checkPreconditions2(message.payload.type, currentState);
1065
+ }
1066
+ } catch (error) {
1067
+ if (error instanceof Error) {
1068
+ throw error;
1069
+ }
1070
+ if (error && typeof error === "object" && "code" in error && error.code === "MODULE_NOT_FOUND") {} else {
1071
+ throw error;
1072
+ }
1073
+ }
1074
+ }
971
1075
  const handler = handlers[0];
972
1076
  if (!handler) {
973
1077
  throw new Error(`Handler not found for ${message.payload.type}`);
974
1078
  }
975
1079
  const data = await handler(message.payload, message);
1080
+ if (this.stateAccessor) {
1081
+ try {
1082
+ const { checkPostconditions: checkPostconditions2, isRuntimeConstraintsEnabled: isRuntimeConstraintsEnabled2 } = await Promise.resolve().then(() => (init_constraints(), exports_constraints));
1083
+ if (isRuntimeConstraintsEnabled2()) {
1084
+ const currentState = this.stateAccessor();
1085
+ checkPostconditions2(message.payload.type, currentState);
1086
+ }
1087
+ } catch (error) {
1088
+ if (error instanceof Error && error.message.includes("Postcondition")) {
1089
+ console.error(`[${this.context}] Postcondition failed:`, error.message);
1090
+ }
1091
+ }
1092
+ }
976
1093
  const response = {
977
1094
  id: message.id,
978
1095
  success: true,
@@ -1170,11 +1287,16 @@ function getCurrentContext() {
1170
1287
  return "background";
1171
1288
  }
1172
1289
  function $sharedState(key, initialValue, options = {}) {
1173
- return createState(key, initialValue, {
1290
+ const sig = createState(key, initialValue, {
1174
1291
  ...options,
1175
1292
  sync: true,
1176
1293
  persist: true
1177
1294
  });
1295
+ const entry = stateRegistry.get(key);
1296
+ if (entry) {
1297
+ sig.loaded = entry.loaded;
1298
+ }
1299
+ return sig;
1178
1300
  }
1179
1301
  function $syncedState(key, initialValue, options = {}) {
1180
1302
  return createState(key, initialValue, {
@@ -1184,11 +1306,16 @@ function $syncedState(key, initialValue, options = {}) {
1184
1306
  });
1185
1307
  }
1186
1308
  function $persistedState(key, initialValue, options = {}) {
1187
- return createState(key, initialValue, {
1309
+ const sig = createState(key, initialValue, {
1188
1310
  ...options,
1189
1311
  sync: false,
1190
1312
  persist: true
1191
1313
  });
1314
+ const entry = stateRegistry.get(key);
1315
+ if (entry) {
1316
+ sig.loaded = entry.loaded;
1317
+ }
1318
+ return sig;
1192
1319
  }
1193
1320
  function $state(initialValue) {
1194
1321
  return signal(initialValue);
@@ -1224,6 +1351,10 @@ Page scripts are execution contexts for content scripts and should not maintain
1224
1351
  Use state in the content script instead, or use $state() for local-only state.`);
1225
1352
  }
1226
1353
  const sig = signal(initialValue);
1354
+ if (options.verify) {
1355
+ const mirror = JSON.parse(JSON.stringify(initialValue));
1356
+ sig.verify = mirror;
1357
+ }
1227
1358
  const entry = {
1228
1359
  signal: sig,
1229
1360
  clock: 0,
@@ -1256,6 +1387,12 @@ Use state in the content script instead, or use $state() for local-only state.`)
1256
1387
  return;
1257
1388
  }
1258
1389
  previousValue = value;
1390
+ if (options.verify) {
1391
+ const verifySignal = sig;
1392
+ if (verifySignal.verify) {
1393
+ Object.assign(verifySignal.verify, JSON.parse(JSON.stringify(value)));
1394
+ }
1395
+ }
1259
1396
  entry.clock++;
1260
1397
  const doUpdate = () => {
1261
1398
  if (options.persist) {
@@ -1504,14 +1641,77 @@ var uiState = signal2({
1504
1641
  sidebarOpen: false,
1505
1642
  selectedPanel: "main"
1506
1643
  });
1644
+
1645
+ // src/index.ts
1646
+ init_constraints();
1647
+
1648
+ // src/shared/lib/validation.ts
1649
+ function checkPrimitiveType(val, type) {
1650
+ if (type === "array")
1651
+ return Array.isArray(val);
1652
+ if (type === "null")
1653
+ return val === null;
1654
+ if (type === "undefined")
1655
+ return val === undefined;
1656
+ return typeof val === type;
1657
+ }
1658
+ function checkFieldType(val, type) {
1659
+ if (typeof type === "string") {
1660
+ return checkPrimitiveType(val, type);
1661
+ }
1662
+ return validateShape(type)(val);
1663
+ }
1664
+ function validateShape(shape) {
1665
+ return (value) => {
1666
+ if (typeof value !== "object" || value === null)
1667
+ return false;
1668
+ const obj = value;
1669
+ for (const [key, type] of Object.entries(shape)) {
1670
+ if (!(key in obj))
1671
+ return false;
1672
+ if (!checkFieldType(obj[key], type))
1673
+ return false;
1674
+ }
1675
+ return true;
1676
+ };
1677
+ }
1678
+ function validateEnum(allowed) {
1679
+ return (value) => {
1680
+ return allowed.includes(value);
1681
+ };
1682
+ }
1683
+ function validateArray(itemValidator) {
1684
+ return (value) => {
1685
+ if (!Array.isArray(value))
1686
+ return false;
1687
+ return value.every(itemValidator);
1688
+ };
1689
+ }
1690
+ function validatePartial(_validator) {
1691
+ return (value) => {
1692
+ if (typeof value !== "object" || value === null)
1693
+ return false;
1694
+ return true;
1695
+ };
1696
+ }
1507
1697
  export {
1698
+ validateShape,
1699
+ validatePartial,
1700
+ validateEnum,
1701
+ validateArray,
1508
1702
  settings,
1509
1703
  runInContext,
1704
+ registerConstraints,
1705
+ registerConstraint,
1510
1706
  quickTest,
1707
+ isRuntimeConstraintsEnabled,
1511
1708
  getMessageBus,
1512
1709
  createTestSuite,
1513
1710
  createContext,
1514
1711
  createChromeAdapters,
1712
+ clearConstraints,
1713
+ checkPreconditions,
1714
+ checkPostconditions,
1515
1715
  TimeoutError,
1516
1716
  TestRunner,
1517
1717
  MessageBus,
@@ -1525,4 +1725,4 @@ export {
1525
1725
  $persistedState
1526
1726
  };
1527
1727
 
1528
- //# debugId=099A20C25FF495A164756E2164756E21
1728
+ //# debugId=20542B0975865A4164756E2164756E21