@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
@@ -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,
@@ -1115,11 +1232,16 @@ function getCurrentContext() {
1115
1232
  return "background";
1116
1233
  }
1117
1234
  function $sharedState(key, initialValue, options = {}) {
1118
- return createState(key, initialValue, {
1235
+ const sig = createState(key, initialValue, {
1119
1236
  ...options,
1120
1237
  sync: true,
1121
1238
  persist: true
1122
1239
  });
1240
+ const entry = stateRegistry.get(key);
1241
+ if (entry) {
1242
+ sig.loaded = entry.loaded;
1243
+ }
1244
+ return sig;
1123
1245
  }
1124
1246
  function $syncedState(key, initialValue, options = {}) {
1125
1247
  return createState(key, initialValue, {
@@ -1129,11 +1251,16 @@ function $syncedState(key, initialValue, options = {}) {
1129
1251
  });
1130
1252
  }
1131
1253
  function $persistedState(key, initialValue, options = {}) {
1132
- return createState(key, initialValue, {
1254
+ const sig = createState(key, initialValue, {
1133
1255
  ...options,
1134
1256
  sync: false,
1135
1257
  persist: true
1136
1258
  });
1259
+ const entry = stateRegistry.get(key);
1260
+ if (entry) {
1261
+ sig.loaded = entry.loaded;
1262
+ }
1263
+ return sig;
1137
1264
  }
1138
1265
  function $state(initialValue) {
1139
1266
  return signal(initialValue);
@@ -1169,6 +1296,10 @@ Page scripts are execution contexts for content scripts and should not maintain
1169
1296
  Use state in the content script instead, or use $state() for local-only state.`);
1170
1297
  }
1171
1298
  const sig = signal(initialValue);
1299
+ if (options.verify) {
1300
+ const mirror = JSON.parse(JSON.stringify(initialValue));
1301
+ sig.verify = mirror;
1302
+ }
1172
1303
  const entry = {
1173
1304
  signal: sig,
1174
1305
  clock: 0,
@@ -1201,6 +1332,12 @@ Use state in the content script instead, or use $state() for local-only state.`)
1201
1332
  return;
1202
1333
  }
1203
1334
  previousValue = value;
1335
+ if (options.verify) {
1336
+ const verifySignal = sig;
1337
+ if (verifySignal.verify) {
1338
+ Object.assign(verifySignal.verify, JSON.parse(JSON.stringify(value)));
1339
+ }
1340
+ }
1204
1341
  entry.clock++;
1205
1342
  const doUpdate = () => {
1206
1343
  if (options.persist) {
@@ -1319,4 +1456,4 @@ export {
1319
1456
  $persistedState
1320
1457
  };
1321
1458
 
1322
- //# debugId=085E9412FB1B6EF164756E2164756E21
1459
+ //# debugId=30E85DBFA071F76364756E2164756E21