@protontech/autofill 0.0.33835493 → 0.0.35059265

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.
@@ -12,7 +12,7 @@ type FlatFeatures<F extends AbstractFeatures> = {
12
12
  [K in keyof F]: FlatFeature<F[K]>;
13
13
  };
14
14
  export declare const flattenFeatures: <F extends AbstractFeatures>(features: F) => FlatFeatures<F>;
15
- export declare const getComputerForFeatures: <F extends AbstractFeatures>(features: F) => FeatureComputer<FlatFeatures<F>>;
15
+ export declare const getComputerForFeatures: (sorted: readonly AbstractFeature[], outputNames: readonly string[]) => FeatureComputer;
16
16
  export declare const topologicalSort: (features: AbstractFeatures) => AbstractFeature<unknown>[];
17
17
  export declare const computeFeatures: <F extends AbstractFeatures>(featureComputer: FeatureComputer<F>, fnode: Fnode) => import("@protontech/autofill/types").ComputedFeatures<F>;
18
18
  export {};
@@ -16,18 +16,16 @@ export const featuresProduct = (feat1, feat2) => feature(`${feat1.name},${feat2.
16
16
  [feat2.name]: feat2,
17
17
  }, (parents) => Number(parents[feat1.name]) * Number(parents[feat2.name]));
18
18
  export const flattenFeatures = (features) => features;
19
- export const getComputerForFeatures = (features) => {
20
- const sorted = topologicalSort(features);
19
+ export const getComputerForFeatures = (sorted, outputNames) => {
20
+ const outputSet = new Set(outputNames);
21
21
  return {
22
22
  compute: (fnode) => {
23
23
  const computed_parents = {};
24
- sorted.forEach((feature) => {
25
- const feature_val = feature.compute(computed_parents, fnode);
26
- computed_parents[feature.name] = feature_val;
27
- });
28
- return Object.fromEntries(Object.values(features).map(({ name }) => [name, computed_parents[name]]));
24
+ for (const feature of sorted)
25
+ computed_parents[feature.name] = feature.compute(computed_parents, fnode);
26
+ return Object.fromEntries(outputNames.map((n) => [n, computed_parents[n]]));
29
27
  },
30
- features: Array.from(Object.values(features)).filter((feat) => !feat.name.startsWith("__")),
28
+ features: sorted.filter((f) => outputSet.has(f.name) && !f.name.startsWith("__")),
31
29
  };
32
30
  };
33
31
  export const topologicalSort = (features) => {
@@ -44,12 +44,16 @@ describe("Feature engineering", () => {
44
44
  const A = feature("A", {}, () => 2);
45
45
  const B = feature("B", { A }, () => 4);
46
46
  const C = featuresProduct(A, B);
47
- expect(getComputerForFeatures({ A, B, C }).compute({})).toStrictEqual({ A: 2, B: 4, "A,B": 8 });
47
+ const features = { A, B, C };
48
+ const outputNames = Object.values(features).map((f) => f.name);
49
+ expect(getComputerForFeatures(topologicalSort(features), outputNames).compute({})).toStrictEqual({ A: 2, B: 4, "A,B": 8 });
48
50
  });
49
51
  test("feature name re-mapping", () => {
50
52
  const A = feature("A", {}, () => 2);
51
53
  const B = feature("_B", { A }, () => 4);
52
54
  const C = feature("C", { A, B }, (p) => p.A + p._B);
53
- expect(getComputerForFeatures({ A, B, C }).compute({})).toStrictEqual({ A: 2, _B: 4, C: 6 });
55
+ const features = { A, B, C };
56
+ const outputNames = Object.values(features).map((f) => f.name);
57
+ expect(getComputerForFeatures(topologicalSort(features), outputNames).compute({})).toStrictEqual({ A: 2, _B: 4, C: 6 });
54
58
  });
55
59
  });
@@ -0,0 +1,3 @@
1
+ import type { FeatureComputer } from "@protontech/autofill/types";
2
+ export declare const setFormFeaturesComputer: (c: FeatureComputer) => void;
3
+ export declare const getFormFeaturesComputer: () => FeatureComputer;
@@ -0,0 +1,9 @@
1
+ let formFeaturesComputer;
2
+ export const setFormFeaturesComputer = (c) => {
3
+ formFeaturesComputer = c;
4
+ };
5
+ export const getFormFeaturesComputer = () => {
6
+ if (!formFeaturesComputer)
7
+ throw new Error("formFeaturesComputer accessed before registration; features/v1 must be initialised first");
8
+ return formFeaturesComputer;
9
+ };
@@ -0,0 +1,14 @@
1
+ export declare const sortedFieldFeatures: import("..").AbstractFeature<unknown>[];
2
+ export declare const fieldFeatureNames: ("text" | "label" | "autocomplete" | "visible" | "attrs" | "isCC" | "isFormLogin" | "parentFormFnode" | "isFormNoop" | "isFormPasswordChange" | "isFormRecovery" | "isFormRegister" | "isIdentity" | "searchField" | "nextField" | "parentFormFeatures" | "prevField" | "prevInput")[];
3
+ export declare const sortedFormFeatures: import("..").AbstractFeature<unknown>[];
4
+ export declare const formFeatureNames: ("__formInputMFACandidates" | "__formMFA" | "formTextMFA" | "formAttrsMFA" | "__formOTPOutlier" | "__formTextAuthenticator" | "inputsMFA" | "__headingsOTPOutlier" | "__inputIterator" | "__linkOTPOutlier" | "visibleFieldsCountScaled" | "visibleInputsCountScaled" | "fieldsetsCountScaled" | "textsCountScaled" | "textareasCountScaled" | "selectsCountScaled" | "disabledCountScaled" | "radiosCountScaled" | "readOnlyCountScaled" | "formComplexityScaled" | "visibleIdentifiersCountScaled" | "hiddenIdentifiersCountScaled" | "usernamesCountScaled" | "emailsCountScaled" | "hiddenCountScaled" | "hiddenPasswordsCountScaled" | "submitsCountScaled" | "identitiesCountScaled" | "ccsCountScaled" | "hasTels" | "hasOAuth" | "hasCaptchas" | "hasFiles" | "hasDate" | "hasNumber" | "oneVisibleField" | "twoVisibleFields" | "threeOrMoreVisibleFields" | "noPasswords" | "onePassword" | "twoPasswords" | "threeOrMorePasswords" | "noIdentifiers" | "oneIdentifier" | "twoIdentifiers" | "threeOrMoreIdentifiers" | "autofocusedIsIdentifier" | "autofocusedIsPassword" | "visibleRatio" | "inputRatio" | "hiddenRatio" | "identifierRatio" | "emailRatio" | "usernameRatio" | "passwordRatio" | "disabledRatio" | "requiredRatio" | "checkboxRatio" | "hiddenIdentifierRatio" | "hiddenPasswordRatio" | "pageLogin" | "formTextLogin" | "formAttrsLogin" | "headingsLogin" | "layoutLogin" | "rememberMeCheckbox" | "troubleLink" | "submitLogin" | "pageRegister" | "formTextRegister" | "formAttrsRegister" | "headingsRegister" | "layoutRegister" | "pwNewRegister" | "pwConfirmRegister" | "submitRegister" | "TOSRef" | "pagePwReset" | "formTextPwReset" | "formAttrsPwReset" | "headingsPwReset" | "layoutPwReset" | "pageRecovery" | "formTextRecovery" | "formAttrsRecovery" | "headingsRecovery" | "layoutRecovery" | "identifierRecovery" | "submitRecovery" | "newsletterForm" | "searchForm" | "multistepForm" | "multiAuthForm" | "multistepForm,multiAuthForm" | "visibleRatio,visibleFieldsCountScaled" | "visibleRatio,visibleIdentifiersCountScaled" | "visibleRatio,visiblePasswordsCountScaled" | "visibleRatio,hiddenIdentifiersCountScaled" | "visibleRatio,hiddenPasswordsCountScaled" | "visibleRatio,multiAuthForm" | "visibleRatio,multistepForm" | "identifierRatio,visibleFieldsCountScaled" | "identifierRatio,visibleIdentifiersCountScaled" | "identifierRatio,visiblePasswordsCountScaled" | "identifierRatio,hiddenIdentifiersCountScaled" | "identifierRatio,hiddenPasswordsCountScaled" | "identifierRatio,multiAuthForm" | "identifierRatio,multistepForm" | "passwordRatio,visibleFieldsCountScaled" | "passwordRatio,visibleIdentifiersCountScaled" | "passwordRatio,visiblePasswordsCountScaled" | "passwordRatio,hiddenIdentifiersCountScaled" | "passwordRatio,hiddenPasswordsCountScaled" | "passwordRatio,multiAuthForm" | "passwordRatio,multistepForm" | "requiredRatio,visibleFieldsCountScaled" | "requiredRatio,visibleIdentifiersCountScaled" | "requiredRatio,visiblePasswordsCountScaled" | "requiredRatio,hiddenIdentifiersCountScaled" | "requiredRatio,hiddenPasswordsCountScaled" | "requiredRatio,multiAuthForm" | "requiredRatio,multistepForm")[];
5
+ export declare const sortedEmailFeatures: import("..").AbstractFeature<unknown>[];
6
+ export declare const emailFeatureNames: ("fieldCC" | "fieldIdentity" | "isSearchField" | "attrEmail" | "autocompleteEmail" | "autocompleteOff" | "typeEmail" | "exactAttrEmail" | "textEmail" | "labelEmail" | "placeholderEmail" | "mfaOutlier")[];
7
+ export declare const sortedOtpFeatures: import("..").AbstractFeature<unknown>[];
8
+ export declare const otpFeatureNames: ("formComplexity" | "fieldCC" | "fieldIdentity" | "formMFA" | "formAuthenticator" | "outlierForm" | "outlierLink" | "outlierHeadings" | "numericMode" | "patternOTP" | "nameMatch" | "idMatch" | "autocompleteOTC" | "singleInput" | "siblingOfInterest" | "attrOTP" | "attrMFA" | "textMFA" | "textAuthenticator" | "labelOTP" | "labelMFA" | "labelAuthenticator" | "outlierMaxLength" | "outlierInputCount" | "outlierEmailMatchScaled" | "outlierField" | "outlierSearch" | "outlierAutocomplete")[];
9
+ export declare const sortedPasswordFeatures: import("..").AbstractFeature<unknown>[];
10
+ export declare const passwordFeatureNames: ("fieldCC" | "fieldIdentity" | "autocompleteOff" | "fieldLogin" | "fieldRegister" | "fieldExotic" | "passwordOutlier" | "autocompleteNew" | "autocompleteCurrent" | "autocompleteOTP" | "attrCurrent" | "textCurrent" | "labelCurrent" | "attrCreate" | "textCreate" | "labelCreate" | "attrConfirm" | "textConfirm" | "labelConfirm" | "attrReset" | "prevPwField" | "prevPwNew" | "prevPwCurrent" | "nextPwField" | "nextPwNew" | "nextPwConfirm" | "nextPwCurrent" | "fieldLogin,autocompleteNew" | "fieldLogin,maybeNew" | "fieldRegister,autocompleteCurrent" | "fieldRegister,maybeCurrent" | "prevPwCurrent,nextPwNew")[];
11
+ export declare const sortedUsernameFeatures: import("..").AbstractFeature<unknown>[];
12
+ export declare const usernameFeatureNames: ("fieldCC" | "fieldIdentity" | "isSearchField" | "autocompleteUsername" | "attrUsername" | "autocompleteEmail" | "autocompleteOff" | "textUsername" | "labelUsername" | "outlierAttrs" | "outlierText" | "outlierLabel" | "outlierEmail" | "firstLoginFormField")[];
13
+ export declare const sortedUsernameHiddenFeatures: import("..").AbstractFeature<unknown>[];
14
+ export declare const usernameHiddenFeatureNames: ("fieldCC" | "fieldIdentity" | "autocompleteUsername" | "attrEmail" | "attrUsername" | "autocompleteEmail" | "fieldExotic" | "visibleReadonly" | "attrMatch" | "valueEmail" | "valueTel" | "valueUsername")[];
@@ -0,0 +1,22 @@
1
+ import { topologicalSort } from "@protontech/autofill/features/feature";
2
+ import { fieldFeatures } from "./v1/abstract.field";
3
+ import { formFeatures } from "./v1/abstract.form";
4
+ import { emailFeatures } from "./v1/field.email";
5
+ import { otpFeatures } from "./v1/field.otp";
6
+ import { passwordFeatures } from "./v1/field.password";
7
+ import { usernameFeatures } from "./v1/field.username";
8
+ import { usernameHiddenFeatures } from "./v1/field.username-hidden";
9
+ export const sortedFieldFeatures = topologicalSort(fieldFeatures);
10
+ export const fieldFeatureNames = Object.values(fieldFeatures).map((f) => f.name);
11
+ export const sortedFormFeatures = topologicalSort(formFeatures);
12
+ export const formFeatureNames = Object.values(formFeatures).map((f) => f.name);
13
+ export const sortedEmailFeatures = topologicalSort(emailFeatures);
14
+ export const emailFeatureNames = Object.values(emailFeatures).map((f) => f.name);
15
+ export const sortedOtpFeatures = topologicalSort(otpFeatures);
16
+ export const otpFeatureNames = Object.values(otpFeatures).map((f) => f.name);
17
+ export const sortedPasswordFeatures = topologicalSort(passwordFeatures);
18
+ export const passwordFeatureNames = Object.values(passwordFeatures).map((f) => f.name);
19
+ export const sortedUsernameFeatures = topologicalSort(usernameFeatures);
20
+ export const usernameFeatureNames = Object.values(usernameFeatures).map((f) => f.name);
21
+ export const sortedUsernameHiddenFeatures = topologicalSort(usernameHiddenFeatures);
22
+ export const usernameHiddenFeatureNames = Object.values(usernameHiddenFeatures).map((f) => f.name);
@@ -1,6 +1,6 @@
1
1
  import { kEmailSelector } from "@protontech/autofill/constants/selectors";
2
2
  import { feature, flattenFeatures } from "@protontech/autofill/features/feature";
3
- import { formFeaturesComputer } from "@protontech/autofill/features/v1/abstract.form";
3
+ import { getFormFeaturesComputer } from "@protontech/autofill/features/registry";
4
4
  import { any } from "@protontech/autofill/utils/combinators";
5
5
  import { matchCCFieldCandidate } from "@protontech/autofill/utils/credit-card";
6
6
  import { getFieldHaystacks } from "@protontech/autofill/utils/extract";
@@ -25,7 +25,7 @@ const parentFormFnode = feature("parentFormFnode", {}, (_, fnode) => getParentFo
25
25
  const parentFormFeatures = feature("parentFormFeatures", { parentFormFnode }, (p) => {
26
26
  const parent = p.parentFormFnode;
27
27
  if (parent && !parent.hasNoteFor("form"))
28
- parent.setNoteFor("form", formFeaturesComputer.compute(parent));
28
+ parent.setNoteFor("form", getFormFeaturesComputer().compute(parent));
29
29
  return parent === null || parent === void 0 ? void 0 : parent.noteFor("form");
30
30
  });
31
31
  const parentFormInputIterator = feature("parentFormInputIterator", { parentFormFeatures }, (p) => { var _a, _b; return (_b = (_a = p.parentFormFeatures) === null || _a === void 0 ? void 0 : _a.__inputIterator) !== null && _b !== void 0 ? _b : null; });