@businessdash/sdk 0.9.60
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/LICENSE +21 -0
- package/README.md +899 -0
- package/dist/adapters-revalidate.d.ts +44 -0
- package/dist/adapters-revalidate.d.ts.map +1 -0
- package/dist/adapters-revalidate.js +68 -0
- package/dist/adapters-revalidate.js.map +1 -0
- package/dist/alpha.d.ts +21 -0
- package/dist/alpha.d.ts.map +1 -0
- package/dist/alpha.js +21 -0
- package/dist/alpha.js.map +1 -0
- package/dist/analytics-core.d.ts +34 -0
- package/dist/analytics-core.d.ts.map +1 -0
- package/dist/analytics-core.js +138 -0
- package/dist/analytics-core.js.map +1 -0
- package/dist/analytics-server.d.ts +54 -0
- package/dist/analytics-server.d.ts.map +1 -0
- package/dist/analytics-server.js +78 -0
- package/dist/analytics-server.js.map +1 -0
- package/dist/attribution-logo.d.ts +2 -0
- package/dist/attribution-logo.d.ts.map +1 -0
- package/dist/attribution-logo.js +5 -0
- package/dist/attribution-logo.js.map +1 -0
- package/dist/auth-handler.d.ts +92 -0
- package/dist/auth-handler.d.ts.map +1 -0
- package/dist/auth-handler.js +277 -0
- package/dist/auth-handler.js.map +1 -0
- package/dist/biab-forms.css +484 -0
- package/dist/cli.d.ts +46 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +1824 -0
- package/dist/cli.js.map +1 -0
- package/dist/client.d.ts +1681 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +2845 -0
- package/dist/client.js.map +1 -0
- package/dist/collections.d.ts +13 -0
- package/dist/collections.d.ts.map +1 -0
- package/dist/collections.js +13 -0
- package/dist/collections.js.map +1 -0
- package/dist/contracts.d.ts +14609 -0
- package/dist/contracts.d.ts.map +1 -0
- package/dist/contracts.js +2428 -0
- package/dist/contracts.js.map +1 -0
- package/dist/data-model-schema.d.ts +962 -0
- package/dist/data-model-schema.d.ts.map +1 -0
- package/dist/data-model-schema.js +2295 -0
- package/dist/data-model-schema.js.map +1 -0
- package/dist/distribution.d.ts +38 -0
- package/dist/distribution.d.ts.map +1 -0
- package/dist/distribution.js +61 -0
- package/dist/distribution.js.map +1 -0
- package/dist/element.d.ts +121 -0
- package/dist/element.d.ts.map +1 -0
- package/dist/element.js +276 -0
- package/dist/element.js.map +1 -0
- package/dist/enums.d.ts +25 -0
- package/dist/enums.d.ts.map +1 -0
- package/dist/enums.js +38 -0
- package/dist/enums.js.map +1 -0
- package/dist/errors.d.ts +195 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +188 -0
- package/dist/errors.js.map +1 -0
- package/dist/forms-core/autocomplete.d.ts +37 -0
- package/dist/forms-core/autocomplete.d.ts.map +1 -0
- package/dist/forms-core/autocomplete.js +82 -0
- package/dist/forms-core/autocomplete.js.map +1 -0
- package/dist/forms-core/business-function.d.ts +61 -0
- package/dist/forms-core/business-function.d.ts.map +1 -0
- package/dist/forms-core/business-function.js +149 -0
- package/dist/forms-core/business-function.js.map +1 -0
- package/dist/forms-core/calculation.d.ts +72 -0
- package/dist/forms-core/calculation.d.ts.map +1 -0
- package/dist/forms-core/calculation.js +103 -0
- package/dist/forms-core/calculation.js.map +1 -0
- package/dist/forms-core/controller.d.ts +249 -0
- package/dist/forms-core/controller.d.ts.map +1 -0
- package/dist/forms-core/controller.js +590 -0
- package/dist/forms-core/controller.js.map +1 -0
- package/dist/forms-core/elements.d.ts +44 -0
- package/dist/forms-core/elements.d.ts.map +1 -0
- package/dist/forms-core/elements.js +68 -0
- package/dist/forms-core/elements.js.map +1 -0
- package/dist/forms-core/email-domains.d.ts +10 -0
- package/dist/forms-core/email-domains.d.ts.map +1 -0
- package/dist/forms-core/email-domains.js +69 -0
- package/dist/forms-core/email-domains.js.map +1 -0
- package/dist/forms-core/file-rules.d.ts +51 -0
- package/dist/forms-core/file-rules.d.ts.map +1 -0
- package/dist/forms-core/file-rules.js +105 -0
- package/dist/forms-core/file-rules.js.map +1 -0
- package/dist/forms-core/formula.d.ts +114 -0
- package/dist/forms-core/formula.d.ts.map +1 -0
- package/dist/forms-core/formula.js +1170 -0
- package/dist/forms-core/formula.js.map +1 -0
- package/dist/forms-core/index.d.ts +24 -0
- package/dist/forms-core/index.d.ts.map +1 -0
- package/dist/forms-core/index.js +28 -0
- package/dist/forms-core/index.js.map +1 -0
- package/dist/forms-core/units.d.ts +49 -0
- package/dist/forms-core/units.d.ts.map +1 -0
- package/dist/forms-core/units.js +255 -0
- package/dist/forms-core/units.js.map +1 -0
- package/dist/forms-core/us-states.d.ts +14 -0
- package/dist/forms-core/us-states.d.ts.map +1 -0
- package/dist/forms-core/us-states.js +66 -0
- package/dist/forms-core/us-states.js.map +1 -0
- package/dist/forms-core/validation.d.ts +266 -0
- package/dist/forms-core/validation.d.ts.map +1 -0
- package/dist/forms-core/validation.js +850 -0
- package/dist/forms-core/validation.js.map +1 -0
- package/dist/forms.d.ts +19 -0
- package/dist/forms.d.ts.map +1 -0
- package/dist/forms.js +29 -0
- package/dist/forms.js.map +1 -0
- package/dist/gallery-types.d.ts +32 -0
- package/dist/gallery-types.d.ts.map +1 -0
- package/dist/gallery-types.js +2 -0
- package/dist/gallery-types.js.map +1 -0
- package/dist/graphql.d.ts +97 -0
- package/dist/graphql.d.ts.map +1 -0
- package/dist/graphql.js +212 -0
- package/dist/graphql.js.map +1 -0
- package/dist/index.cjs +19448 -0
- package/dist/index.d.cts +19 -0
- package/dist/index.d.mts +19 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/marketing-schema.d.ts +216 -0
- package/dist/marketing-schema.d.ts.map +1 -0
- package/dist/marketing-schema.js +200 -0
- package/dist/marketing-schema.js.map +1 -0
- package/dist/mcp.d.ts +42 -0
- package/dist/mcp.d.ts.map +1 -0
- package/dist/mcp.js +87 -0
- package/dist/mcp.js.map +1 -0
- package/dist/native.d.ts +45 -0
- package/dist/native.d.ts.map +1 -0
- package/dist/native.js +43 -0
- package/dist/native.js.map +1 -0
- package/dist/next-revalidate.d.ts +43 -0
- package/dist/next-revalidate.d.ts.map +1 -0
- package/dist/next-revalidate.js +84 -0
- package/dist/next-revalidate.js.map +1 -0
- package/dist/parallel-pages.d.ts +102 -0
- package/dist/parallel-pages.d.ts.map +1 -0
- package/dist/parallel-pages.js +108 -0
- package/dist/parallel-pages.js.map +1 -0
- package/dist/payment-icons.d.ts +66 -0
- package/dist/payment-icons.d.ts.map +1 -0
- package/dist/payment-icons.js +160 -0
- package/dist/payment-icons.js.map +1 -0
- package/dist/proxy.d.ts +67 -0
- package/dist/proxy.d.ts.map +1 -0
- package/dist/proxy.js +97 -0
- package/dist/proxy.js.map +1 -0
- package/dist/react-analytics.d.ts +39 -0
- package/dist/react-analytics.d.ts.map +1 -0
- package/dist/react-analytics.js +59 -0
- package/dist/react-analytics.js.map +1 -0
- package/dist/react-attribution.d.ts +99 -0
- package/dist/react-attribution.d.ts.map +1 -0
- package/dist/react-attribution.js +52 -0
- package/dist/react-attribution.js.map +1 -0
- package/dist/react-marketing.d.ts +181 -0
- package/dist/react-marketing.d.ts.map +1 -0
- package/dist/react-marketing.js +215 -0
- package/dist/react-marketing.js.map +1 -0
- package/dist/react.d.ts +727 -0
- package/dist/react.d.ts.map +1 -0
- package/dist/react.js +2418 -0
- package/dist/react.js.map +1 -0
- package/dist/reserved-paths.d.ts +24 -0
- package/dist/reserved-paths.d.ts.map +1 -0
- package/dist/reserved-paths.js +60 -0
- package/dist/reserved-paths.js.map +1 -0
- package/dist/revalidate-verify.d.ts +30 -0
- package/dist/revalidate-verify.d.ts.map +1 -0
- package/dist/revalidate-verify.js +74 -0
- package/dist/revalidate-verify.js.map +1 -0
- package/dist/sdk.d.ts +678 -0
- package/dist/sdk.d.ts.map +1 -0
- package/dist/sdk.js +801 -0
- package/dist/sdk.js.map +1 -0
- package/dist/seo.d.ts +218 -0
- package/dist/seo.d.ts.map +1 -0
- package/dist/seo.js +309 -0
- package/dist/seo.js.map +1 -0
- package/dist/socials.d.ts +47 -0
- package/dist/socials.d.ts.map +1 -0
- package/dist/socials.js +172 -0
- package/dist/socials.js.map +1 -0
- package/dist/static.d.ts +14 -0
- package/dist/static.d.ts.map +1 -0
- package/dist/static.js +14 -0
- package/dist/static.js.map +1 -0
- package/dist/url-pattern.d.ts +47 -0
- package/dist/url-pattern.d.ts.map +1 -0
- package/dist/url-pattern.js +124 -0
- package/dist/url-pattern.js.map +1 -0
- package/dist/vanilla.d.ts +77 -0
- package/dist/vanilla.d.ts.map +1 -0
- package/dist/vanilla.js +903 -0
- package/dist/vanilla.js.map +1 -0
- package/openapi.json +13779 -0
- package/package.json +204 -0
- package/src/adapters-revalidate.ts +88 -0
- package/src/alpha.ts +89 -0
- package/src/analytics-core.ts +175 -0
- package/src/analytics-server.ts +99 -0
- package/src/angular/biab-form.component.ts +1443 -0
- package/src/angular/index.ts +26 -0
- package/src/attribution-logo.ts +5 -0
- package/src/auth-handler.ts +352 -0
- package/src/cli.ts +2517 -0
- package/src/client.ts +3578 -0
- package/src/collections.ts +101 -0
- package/src/contracts.ts +3390 -0
- package/src/data-model-schema.ts +4042 -0
- package/src/distribution.ts +73 -0
- package/src/element.ts +321 -0
- package/src/enums.ts +65 -0
- package/src/errors.ts +338 -0
- package/src/forms-core/autocomplete.ts +97 -0
- package/src/forms-core/business-function.ts +209 -0
- package/src/forms-core/calculation.ts +167 -0
- package/src/forms-core/controller.ts +922 -0
- package/src/forms-core/elements.ts +86 -0
- package/src/forms-core/email-domains.ts +68 -0
- package/src/forms-core/file-rules.ts +123 -0
- package/src/forms-core/formula.ts +1339 -0
- package/src/forms-core/index.ts +122 -0
- package/src/forms-core/units.ts +308 -0
- package/src/forms-core/us-states.ts +68 -0
- package/src/forms-core/validation.ts +1037 -0
- package/src/forms.ts +63 -0
- package/src/gallery-types.ts +31 -0
- package/src/graphql.ts +295 -0
- package/src/index.ts +505 -0
- package/src/marketing-schema.ts +395 -0
- package/src/mcp.ts +108 -0
- package/src/native.ts +73 -0
- package/src/next-revalidate.ts +124 -0
- package/src/parallel-pages.ts +192 -0
- package/src/payment-icons.ts +205 -0
- package/src/proxy.ts +173 -0
- package/src/qwik.tsx +1234 -0
- package/src/react-analytics.tsx +76 -0
- package/src/react-attribution.tsx +192 -0
- package/src/react-marketing.tsx +338 -0
- package/src/react.tsx +5495 -0
- package/src/reserved-paths.ts +65 -0
- package/src/revalidate-verify.ts +98 -0
- package/src/sdk.ts +1671 -0
- package/src/seo.ts +488 -0
- package/src/socials.ts +230 -0
- package/src/solid.tsx +1466 -0
- package/src/static.ts +21 -0
- package/src/styles/biab-forms.css +484 -0
- package/src/svelte/BiabForm.svelte +1069 -0
- package/src/svelte/context.ts +57 -0
- package/src/svelte/index.ts +79 -0
- package/src/url-pattern.ts +153 -0
- package/src/vanilla.ts +1290 -0
- package/src/vue/BiabForm.vue +1538 -0
- package/src/vue/index.ts +119 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Small, framework-free helpers the bindings share when rendering elements.
|
|
3
|
+
*
|
|
4
|
+
* Anything here would otherwise be copy-pasted into React, Svelte, Vue, Angular,
|
|
5
|
+
* Solid, Qwik and vanilla — and then drift. The dashboard renderer keeps its own
|
|
6
|
+
* copy of the threshold only because it can't import from the SDK; the values
|
|
7
|
+
* are deliberately identical.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Past this many options a dropdown grows a search affordance on its own.
|
|
11
|
+
* Scrolling a long list to find one entry is the worse default, and an author
|
|
12
|
+
* shouldn't have to notice their list got long. Mirrors `SEARCHABLE_THRESHOLD`
|
|
13
|
+
* in the dashboard builder's `constants.tsx`.
|
|
14
|
+
*/
|
|
15
|
+
export const SEARCHABLE_THRESHOLD = 10;
|
|
16
|
+
/** Should this dropdown offer search? Either the author asked for it (the
|
|
17
|
+
* ComboBox card sets `display: "combobox"`) or the list is long enough. */
|
|
18
|
+
export function shouldSearchOptions(optionCount, display) {
|
|
19
|
+
return display === "combobox" || optionCount > SEARCHABLE_THRESHOLD;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Where BIAB serves icon art.
|
|
23
|
+
*
|
|
24
|
+
* The `icon_select` element stores an icon NAME, and rendering it back needs the
|
|
25
|
+
* icon set. The SDK deliberately doesn't bundle one: it's ~1,600 icons, and
|
|
26
|
+
* three of the bindings can't import a React package anyway. Names resolve to
|
|
27
|
+
* `<img src="…/api/icons/<name>.svg">`, so the platform stays the single source
|
|
28
|
+
* of truth for what a name means.
|
|
29
|
+
*
|
|
30
|
+
* Override with `NEXT_PUBLIC_BIAB_ORIGIN` when pointing a consumer app at a
|
|
31
|
+
* non-production BIAB.
|
|
32
|
+
*/
|
|
33
|
+
export const BIAB_ICON_BASE = (() => {
|
|
34
|
+
// Read through `globalThis` rather than the bare `process` identifier: the
|
|
35
|
+
// SDK is consumed by browser bundlers that have no `@types/node`, where
|
|
36
|
+
// naming `process` directly fails to compile (and can throw at runtime).
|
|
37
|
+
const env = globalThis.process?.env;
|
|
38
|
+
return env?.["NEXT_PUBLIC_BIAB_ORIGIN"] || "https://www.biab.app";
|
|
39
|
+
})();
|
|
40
|
+
/** SVG URL for one icon name. */
|
|
41
|
+
export function iconUrl(name) {
|
|
42
|
+
return `${BIAB_ICON_BASE}/api/icons/${encodeURIComponent(name)}.svg`;
|
|
43
|
+
}
|
|
44
|
+
/** The lazily-fetched icon-name index (only needed when an author hasn't
|
|
45
|
+
* curated `iconConfig.allowedIcons`). */
|
|
46
|
+
export const ICON_INDEX_URL = `${BIAB_ICON_BASE}/api/icons`;
|
|
47
|
+
/** Narrow an icon list by a search query, capped so the grid never mounts
|
|
48
|
+
* thousands of nodes at once. */
|
|
49
|
+
export function filterIconNames(names, query, limit = 120) {
|
|
50
|
+
const q = query.trim().toLowerCase();
|
|
51
|
+
return (q ? names.filter((n) => n.includes(q)) : names).slice(0, limit);
|
|
52
|
+
}
|
|
53
|
+
/** Fetch the icon-name index. Resolves to `[]` on any failure — a missing index
|
|
54
|
+
* leaves the picker's grid empty, which is recoverable; throwing here would
|
|
55
|
+
* take the whole form down. */
|
|
56
|
+
export async function fetchIconNames() {
|
|
57
|
+
try {
|
|
58
|
+
const res = await fetch(ICON_INDEX_URL);
|
|
59
|
+
if (!res.ok)
|
|
60
|
+
return [];
|
|
61
|
+
const data = (await res.json());
|
|
62
|
+
return data.icons ?? [];
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
return [];
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=elements.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"elements.js","sourceRoot":"","sources":["../../src/forms-core/elements.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH;;;;;GAKG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,EAAE,CAAC;AAEvC;4EAC4E;AAC5E,MAAM,UAAU,mBAAmB,CAClC,WAAmB,EACnB,OAAgB;IAEhB,OAAO,OAAO,KAAK,UAAU,IAAI,WAAW,GAAG,oBAAoB,CAAC;AACrE,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,cAAc,GAAW,CAAC,GAAG,EAAE;IAC3C,2EAA2E;IAC3E,wEAAwE;IACxE,yEAAyE;IACzE,MAAM,GAAG,GACR,UAGA,CAAC,OAAO,EAAE,GAAG,CAAC;IACf,OAAO,GAAG,EAAE,CAAC,yBAAyB,CAAC,IAAI,sBAAsB,CAAC;AACnE,CAAC,CAAC,EAAE,CAAC;AAEL,iCAAiC;AACjC,MAAM,UAAU,OAAO,CAAC,IAAY;IACnC,OAAO,GAAG,cAAc,cAAc,kBAAkB,CAAC,IAAI,CAAC,MAAM,CAAC;AACtE,CAAC;AAED;0CAC0C;AAC1C,MAAM,CAAC,MAAM,cAAc,GAAG,GAAG,cAAc,YAAY,CAAC;AAE5D;kCACkC;AAClC,MAAM,UAAU,eAAe,CAC9B,KAAwB,EACxB,KAAa,EACb,KAAK,GAAG,GAAG;IAEX,MAAM,CAAC,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACrC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,CAC5D,CAAC,EACD,KAAK,CACO,CAAC;AACf,CAAC;AAED;;gCAEgC;AAChC,MAAM,CAAC,KAAK,UAAU,cAAc;IACnC,IAAI,CAAC;QACJ,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,cAAc,CAAC,CAAC;QACxC,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,OAAO,EAAE,CAAC;QACvB,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAyB,CAAC;QACxD,OAAO,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;IACzB,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,EAAE,CAAC;IACX,CAAC;AACF,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Free / consumer webmail detection for the email field's "business only" rule.
|
|
3
|
+
* Mirror of the app's `src/lib/onboarding-email-domain.ts` (the consumer-domain
|
|
4
|
+
* set + helpers) so the SDK's client validation agrees with the server.
|
|
5
|
+
*/
|
|
6
|
+
/** The lowercase host portion of an email, or null when malformed. */
|
|
7
|
+
export declare function getEmailDomain(email: string): string | null;
|
|
8
|
+
/** True for free/personal webmail hosts (so "business only" can reject them). */
|
|
9
|
+
export declare function isConsumerEmailDomain(host: string): boolean;
|
|
10
|
+
//# sourceMappingURL=email-domains.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"email-domains.d.ts","sourceRoot":"","sources":["../../src/forms-core/email-domains.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AA+CH,sEAAsE;AACtE,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAO3D;AAED,iFAAiF;AACjF,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAK3D"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Free / consumer webmail detection for the email field's "business only" rule.
|
|
3
|
+
* Mirror of the app's `src/lib/onboarding-email-domain.ts` (the consumer-domain
|
|
4
|
+
* set + helpers) so the SDK's client validation agrees with the server.
|
|
5
|
+
*/
|
|
6
|
+
const CONSUMER_EMAIL_DOMAINS = new Set([
|
|
7
|
+
"gmail.com",
|
|
8
|
+
"googlemail.com",
|
|
9
|
+
"yahoo.com",
|
|
10
|
+
"yahoo.co.uk",
|
|
11
|
+
"yahoo.fr",
|
|
12
|
+
"yahoo.de",
|
|
13
|
+
"hotmail.com",
|
|
14
|
+
"hotmail.co.uk",
|
|
15
|
+
"outlook.com",
|
|
16
|
+
"live.com",
|
|
17
|
+
"msn.com",
|
|
18
|
+
"icloud.com",
|
|
19
|
+
"me.com",
|
|
20
|
+
"mac.com",
|
|
21
|
+
"aol.com",
|
|
22
|
+
"proton.me",
|
|
23
|
+
"protonmail.com",
|
|
24
|
+
"pm.me",
|
|
25
|
+
"yandex.com",
|
|
26
|
+
"yandex.ru",
|
|
27
|
+
"mail.com",
|
|
28
|
+
"gmx.com",
|
|
29
|
+
"gmx.de",
|
|
30
|
+
"gmx.net",
|
|
31
|
+
"hey.com",
|
|
32
|
+
"fastmail.com",
|
|
33
|
+
"fastmail.fm",
|
|
34
|
+
"duck.com",
|
|
35
|
+
"tutanota.com",
|
|
36
|
+
"tutamail.com",
|
|
37
|
+
"qq.com",
|
|
38
|
+
"163.com",
|
|
39
|
+
"sbcglobal.net",
|
|
40
|
+
"att.net",
|
|
41
|
+
"verizon.net",
|
|
42
|
+
"comcast.net",
|
|
43
|
+
"btinternet.com",
|
|
44
|
+
"sky.com",
|
|
45
|
+
"orange.fr",
|
|
46
|
+
"wanadoo.fr",
|
|
47
|
+
"free.fr",
|
|
48
|
+
"laposte.net",
|
|
49
|
+
]);
|
|
50
|
+
/** The lowercase host portion of an email, or null when malformed. */
|
|
51
|
+
export function getEmailDomain(email) {
|
|
52
|
+
const at = email.lastIndexOf("@");
|
|
53
|
+
if (at < 0 || at === email.length - 1)
|
|
54
|
+
return null;
|
|
55
|
+
return email
|
|
56
|
+
.slice(at + 1)
|
|
57
|
+
.trim()
|
|
58
|
+
.toLowerCase();
|
|
59
|
+
}
|
|
60
|
+
/** True for free/personal webmail hosts (so "business only" can reject them). */
|
|
61
|
+
export function isConsumerEmailDomain(host) {
|
|
62
|
+
const h = host.trim().toLowerCase();
|
|
63
|
+
if (CONSUMER_EMAIL_DOMAINS.has(h))
|
|
64
|
+
return true;
|
|
65
|
+
if (h.endsWith(".gmail.com") || h.endsWith(".googlemail.com"))
|
|
66
|
+
return true;
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=email-domains.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"email-domains.js","sourceRoot":"","sources":["../../src/forms-core/email-domains.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,sBAAsB,GAAG,IAAI,GAAG,CAAC;IACtC,WAAW;IACX,gBAAgB;IAChB,WAAW;IACX,aAAa;IACb,UAAU;IACV,UAAU;IACV,aAAa;IACb,eAAe;IACf,aAAa;IACb,UAAU;IACV,SAAS;IACT,YAAY;IACZ,QAAQ;IACR,SAAS;IACT,SAAS;IACT,WAAW;IACX,gBAAgB;IAChB,OAAO;IACP,YAAY;IACZ,WAAW;IACX,UAAU;IACV,SAAS;IACT,QAAQ;IACR,SAAS;IACT,SAAS;IACT,cAAc;IACd,aAAa;IACb,UAAU;IACV,cAAc;IACd,cAAc;IACd,QAAQ;IACR,SAAS;IACT,eAAe;IACf,SAAS;IACT,aAAa;IACb,aAAa;IACb,gBAAgB;IAChB,SAAS;IACT,WAAW;IACX,YAAY;IACZ,SAAS;IACT,aAAa;CACb,CAAC,CAAC;AAEH,sEAAsE;AACtE,MAAM,UAAU,cAAc,CAAC,KAAa;IAC3C,MAAM,EAAE,GAAG,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAClC,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,KAAK,KAAK,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IACnD,OAAO,KAAK;SACV,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC;SACb,IAAI,EAAE;SACN,WAAW,EAAE,CAAC;AACjB,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,qBAAqB,CAAC,IAAY;IACjD,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACpC,IAAI,sBAAsB,CAAC,GAAG,CAAC,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IAC/C,IAAI,CAAC,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,iBAAiB,CAAC;QAAE,OAAO,IAAI,CAAC;IAC3E,OAAO,KAAK,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File-upload rules — the single source of truth for what a `file_upload` field
|
|
3
|
+
* accepts, shared by the builder picker, the live renderers, and all submission
|
|
4
|
+
* validators (so the client never disagrees with the server).
|
|
5
|
+
*
|
|
6
|
+
* Three concerns:
|
|
7
|
+
* - **iOS formats:** iPhones hand back HEIC photos + HEVC/`.mov` video. When a
|
|
8
|
+
* field allows images/video we transparently accept those too, so a visitor
|
|
9
|
+
* isn't blocked by their camera's default codec.
|
|
10
|
+
* - **Per-file rules:** allowed type + max size (MB), per the field config.
|
|
11
|
+
* - **Form-wide cap:** at most {@link FORM_WIDE_MAX_FILES} files across ALL
|
|
12
|
+
* file fields in one submission (anti-abuse; a field's own `maxFiles` still
|
|
13
|
+
* caps that field).
|
|
14
|
+
*
|
|
15
|
+
* Pure + isomorphic (no DOM, no DB). The SDK mirrors it.
|
|
16
|
+
*/
|
|
17
|
+
/** HEIC/HEIF still-image formats (iPhone default photo codec). */
|
|
18
|
+
export declare const IOS_IMAGE_TYPES: readonly ["image/heic", "image/heif"];
|
|
19
|
+
/** iPhone video container (`.mov`, typically HEVC). */
|
|
20
|
+
export declare const IOS_VIDEO_TYPES: readonly ["video/quicktime"];
|
|
21
|
+
/** Max total files across every `file_upload` field in one submission. */
|
|
22
|
+
export declare const FORM_WIDE_MAX_FILES = 5;
|
|
23
|
+
export interface FileRule {
|
|
24
|
+
/** Allowed MIME types / wildcards (e.g. `image/*`) / extensions (`.pdf`). */
|
|
25
|
+
allowedTypes?: string[] | undefined;
|
|
26
|
+
/** Per-field file count cap. */
|
|
27
|
+
maxFiles?: number | undefined;
|
|
28
|
+
/** Per-file size cap in MB. */
|
|
29
|
+
maxSize?: number | undefined;
|
|
30
|
+
}
|
|
31
|
+
/** A minimal file descriptor — works for a real `File` or a stored value. */
|
|
32
|
+
export interface FileLike {
|
|
33
|
+
name: string;
|
|
34
|
+
type?: string | undefined;
|
|
35
|
+
size?: number | undefined;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Expand a field's `allowedTypes` to also accept iOS HEIC/HEVC when the field
|
|
39
|
+
* already allows images/video, then format the `<input accept>` attribute.
|
|
40
|
+
* Returns undefined (= accept anything) when no allow-list is set.
|
|
41
|
+
*/
|
|
42
|
+
export declare function buildAcceptAttr(allowed?: string[]): string | undefined;
|
|
43
|
+
/** The allow-list plus the iOS formats implied by it (deduped, order-stable). */
|
|
44
|
+
export declare function expandAllowedTypes(allowed: string[]): string[];
|
|
45
|
+
/** Is `file` an accepted type for `allowed`? Empty/absent allow-list = anything.
|
|
46
|
+
* Handles exact MIME, `type/*` wildcards, and `.ext` entries; iOS HEIC/HEVC are
|
|
47
|
+
* honored whenever images/video are allowed. */
|
|
48
|
+
export declare function isFileTypeAllowed(file: FileLike, allowed?: string[]): boolean;
|
|
49
|
+
/** Per-file validation (type + size). Returns an error string or null. */
|
|
50
|
+
export declare function validateFile(file: FileLike, rule: FileRule): string | null;
|
|
51
|
+
//# sourceMappingURL=file-rules.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-rules.d.ts","sourceRoot":"","sources":["../../src/forms-core/file-rules.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,kEAAkE;AAClE,eAAO,MAAM,eAAe,uCAAwC,CAAC;AACrE,uDAAuD;AACvD,eAAO,MAAM,eAAe,8BAA+B,CAAC;AAE5D,0EAA0E;AAC1E,eAAO,MAAM,mBAAmB,IAAI,CAAC;AAErC,MAAM,WAAW,QAAQ;IACxB,6EAA6E;IAC7E,YAAY,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IACpC,gCAAgC;IAChC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,+BAA+B;IAC/B,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC7B;AAED,6EAA6E;AAC7E,MAAM,WAAW,QAAQ;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC1B;AAiBD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,CAGtE;AAED,iFAAiF;AACjF,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAe9D;AAED;;iDAEiD;AACjD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,GAAG,OAAO,CAmB7E;AAED,0EAA0E;AAC1E,wBAAgB,YAAY,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,GAAG,MAAM,GAAG,IAAI,CAa1E"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File-upload rules — the single source of truth for what a `file_upload` field
|
|
3
|
+
* accepts, shared by the builder picker, the live renderers, and all submission
|
|
4
|
+
* validators (so the client never disagrees with the server).
|
|
5
|
+
*
|
|
6
|
+
* Three concerns:
|
|
7
|
+
* - **iOS formats:** iPhones hand back HEIC photos + HEVC/`.mov` video. When a
|
|
8
|
+
* field allows images/video we transparently accept those too, so a visitor
|
|
9
|
+
* isn't blocked by their camera's default codec.
|
|
10
|
+
* - **Per-file rules:** allowed type + max size (MB), per the field config.
|
|
11
|
+
* - **Form-wide cap:** at most {@link FORM_WIDE_MAX_FILES} files across ALL
|
|
12
|
+
* file fields in one submission (anti-abuse; a field's own `maxFiles` still
|
|
13
|
+
* caps that field).
|
|
14
|
+
*
|
|
15
|
+
* Pure + isomorphic (no DOM, no DB). The SDK mirrors it.
|
|
16
|
+
*/
|
|
17
|
+
/** HEIC/HEIF still-image formats (iPhone default photo codec). */
|
|
18
|
+
export const IOS_IMAGE_TYPES = ["image/heic", "image/heif"];
|
|
19
|
+
/** iPhone video container (`.mov`, typically HEVC). */
|
|
20
|
+
export const IOS_VIDEO_TYPES = ["video/quicktime"];
|
|
21
|
+
/** Max total files across every `file_upload` field in one submission. */
|
|
22
|
+
export const FORM_WIDE_MAX_FILES = 5;
|
|
23
|
+
function ext(name) {
|
|
24
|
+
const dot = name.lastIndexOf(".");
|
|
25
|
+
return dot >= 0 ? name.slice(dot).toLowerCase() : "";
|
|
26
|
+
}
|
|
27
|
+
/** Does `image/*` / `video/*` appear in the allow-list (so iOS codecs apply)? */
|
|
28
|
+
function allowsImages(allowed) {
|
|
29
|
+
return allowed.some((a) => a === "image/*" || (a.startsWith("image/") && !a.includes("heic")));
|
|
30
|
+
}
|
|
31
|
+
function allowsVideo(allowed) {
|
|
32
|
+
return allowed.some((a) => a === "video/*" || a.startsWith("video/"));
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Expand a field's `allowedTypes` to also accept iOS HEIC/HEVC when the field
|
|
36
|
+
* already allows images/video, then format the `<input accept>` attribute.
|
|
37
|
+
* Returns undefined (= accept anything) when no allow-list is set.
|
|
38
|
+
*/
|
|
39
|
+
export function buildAcceptAttr(allowed) {
|
|
40
|
+
if (!allowed || allowed.length === 0)
|
|
41
|
+
return undefined;
|
|
42
|
+
return expandAllowedTypes(allowed).join(",");
|
|
43
|
+
}
|
|
44
|
+
/** The allow-list plus the iOS formats implied by it (deduped, order-stable). */
|
|
45
|
+
export function expandAllowedTypes(allowed) {
|
|
46
|
+
const out = [...allowed];
|
|
47
|
+
const add = (t) => {
|
|
48
|
+
if (!out.includes(t))
|
|
49
|
+
out.push(t);
|
|
50
|
+
};
|
|
51
|
+
if (allowsImages(allowed)) {
|
|
52
|
+
for (const t of IOS_IMAGE_TYPES)
|
|
53
|
+
add(t);
|
|
54
|
+
add(".heic");
|
|
55
|
+
add(".heif");
|
|
56
|
+
}
|
|
57
|
+
if (allowsVideo(allowed)) {
|
|
58
|
+
for (const t of IOS_VIDEO_TYPES)
|
|
59
|
+
add(t);
|
|
60
|
+
add(".mov");
|
|
61
|
+
}
|
|
62
|
+
return out;
|
|
63
|
+
}
|
|
64
|
+
/** Is `file` an accepted type for `allowed`? Empty/absent allow-list = anything.
|
|
65
|
+
* Handles exact MIME, `type/*` wildcards, and `.ext` entries; iOS HEIC/HEVC are
|
|
66
|
+
* honored whenever images/video are allowed. */
|
|
67
|
+
export function isFileTypeAllowed(file, allowed) {
|
|
68
|
+
if (!allowed || allowed.length === 0)
|
|
69
|
+
return true;
|
|
70
|
+
const list = expandAllowedTypes(allowed);
|
|
71
|
+
const type = (file.type ?? "").toLowerCase();
|
|
72
|
+
const fileExt = ext(file.name);
|
|
73
|
+
for (const raw of list) {
|
|
74
|
+
const a = raw.toLowerCase().trim();
|
|
75
|
+
if (!a)
|
|
76
|
+
continue;
|
|
77
|
+
if (a.startsWith(".")) {
|
|
78
|
+
if (fileExt === a)
|
|
79
|
+
return true;
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
if (a.endsWith("/*")) {
|
|
83
|
+
if (type.startsWith(`${a.slice(0, -1)}`))
|
|
84
|
+
return true;
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
if (type && type === a)
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
/** Per-file validation (type + size). Returns an error string or null. */
|
|
93
|
+
export function validateFile(file, rule) {
|
|
94
|
+
if (!isFileTypeAllowed(file, rule.allowedTypes)) {
|
|
95
|
+
return `File type not allowed: ${file.type || file.name}`;
|
|
96
|
+
}
|
|
97
|
+
if (typeof rule.maxSize === "number" &&
|
|
98
|
+
rule.maxSize > 0 &&
|
|
99
|
+
typeof file.size === "number" &&
|
|
100
|
+
file.size > rule.maxSize * 1024 * 1024) {
|
|
101
|
+
return `"${file.name}" exceeds the ${rule.maxSize} MB limit.`;
|
|
102
|
+
}
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=file-rules.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-rules.js","sourceRoot":"","sources":["../../src/forms-core/file-rules.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Safe, isomorphic formula engine for Business Functions + the Math form element.
|
|
3
|
+
*
|
|
4
|
+
* SECURITY: there is NO `eval`, `new Function`, or any dynamic code execution.
|
|
5
|
+
* A formula is tokenized → parsed into an AST → walked by an evaluator that only
|
|
6
|
+
* does arithmetic/logic and calls a fixed, whitelisted function table. Unknown
|
|
7
|
+
* identifiers (that aren't a provided variable) and unknown functions are hard
|
|
8
|
+
* errors. The same module runs on the client (non-sensitive functions, live) and
|
|
9
|
+
* the server (all functions) so results never disagree. The SDK keeps a mirror at
|
|
10
|
+
* `biab-dev/src/forms-core/formula.ts`.
|
|
11
|
+
*
|
|
12
|
+
* Values are scalars: number | string | boolean. (Tables / arrays are a
|
|
13
|
+
* fast-follow.) Function reference: see FORMULA_FUNCTIONS.
|
|
14
|
+
*/
|
|
15
|
+
/** A record value — e.g. a measurement field `{ size, unit, base }`, a CRM record,
|
|
16
|
+
* or a multi-output function result. Fields are read with member access
|
|
17
|
+
* (`source.field`). */
|
|
18
|
+
export interface FormulaObject {
|
|
19
|
+
[key: string]: FormulaValue;
|
|
20
|
+
}
|
|
21
|
+
export type FormulaValue = number | string | boolean | FormulaObject;
|
|
22
|
+
export type FormulaVars = Record<string, FormulaValue | null | undefined>;
|
|
23
|
+
/** Public guard: is this value a record (object) rather than a scalar? */
|
|
24
|
+
export declare function isFormulaObjectValue(v: unknown): v is FormulaObject;
|
|
25
|
+
export type FormulaResult = {
|
|
26
|
+
ok: true;
|
|
27
|
+
value: FormulaValue;
|
|
28
|
+
} | {
|
|
29
|
+
ok: false;
|
|
30
|
+
error: string;
|
|
31
|
+
};
|
|
32
|
+
type Node = {
|
|
33
|
+
t: "num";
|
|
34
|
+
v: number;
|
|
35
|
+
} | {
|
|
36
|
+
t: "str";
|
|
37
|
+
v: string;
|
|
38
|
+
} | {
|
|
39
|
+
t: "bool";
|
|
40
|
+
v: boolean;
|
|
41
|
+
} | {
|
|
42
|
+
t: "var";
|
|
43
|
+
name: string;
|
|
44
|
+
} | {
|
|
45
|
+
t: "member";
|
|
46
|
+
obj: Node;
|
|
47
|
+
key: string;
|
|
48
|
+
} | {
|
|
49
|
+
t: "unary";
|
|
50
|
+
op: string;
|
|
51
|
+
arg: Node;
|
|
52
|
+
} | {
|
|
53
|
+
t: "binary";
|
|
54
|
+
op: string;
|
|
55
|
+
left: Node;
|
|
56
|
+
right: Node;
|
|
57
|
+
} | {
|
|
58
|
+
t: "call";
|
|
59
|
+
name: string;
|
|
60
|
+
args: Node[];
|
|
61
|
+
};
|
|
62
|
+
/** A formula AST plus the names it references (for validation/UI). */
|
|
63
|
+
export interface ParsedFormula {
|
|
64
|
+
ast: Node;
|
|
65
|
+
/** Distinct variable identifiers referenced (excludes function names). */
|
|
66
|
+
variables: string[];
|
|
67
|
+
/** Distinct function names called (built-in or user/business functions). */
|
|
68
|
+
functions: string[];
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* A user/business function callable from another formula by name. `params` are
|
|
72
|
+
* the ordered variable names the call's arguments bind to. Pass a map of these
|
|
73
|
+
* to {@link evaluateFormula} so formulas can reference other functions.
|
|
74
|
+
*/
|
|
75
|
+
export interface UserFunctionDef {
|
|
76
|
+
params: string[];
|
|
77
|
+
formula: ParsedFormula;
|
|
78
|
+
}
|
|
79
|
+
export interface EvalOptions {
|
|
80
|
+
/** name → user function, enabling formula-references-formula composition. */
|
|
81
|
+
functions?: Record<string, UserFunctionDef>;
|
|
82
|
+
}
|
|
83
|
+
export type FormulaCategory = "math" | "statistical" | "logical" | "text" | "date" | "reference" | "geo";
|
|
84
|
+
interface FnDef {
|
|
85
|
+
category: FormulaCategory;
|
|
86
|
+
/** Min args (inclusive). */
|
|
87
|
+
min: number;
|
|
88
|
+
/** Max args, or null for variadic. */
|
|
89
|
+
max: number | null;
|
|
90
|
+
help: string;
|
|
91
|
+
fn: (args: FormulaValue[]) => FormulaValue;
|
|
92
|
+
}
|
|
93
|
+
export declare const FORMULA_FUNCTIONS: Record<string, FnDef>;
|
|
94
|
+
/** Parse a formula into an AST + its referenced variables. Throws on syntax error. */
|
|
95
|
+
export declare function parseFormula(src: string): ParsedFormula;
|
|
96
|
+
/** Evaluate a parsed formula against a variables context. Never throws — returns
|
|
97
|
+
* a controlled result. */
|
|
98
|
+
export declare function evaluateFormula(parsed: ParsedFormula, vars: FormulaVars, options?: EvalOptions): FormulaResult;
|
|
99
|
+
/** Parse + evaluate in one call. Never throws. */
|
|
100
|
+
export declare function runFormula(src: string, vars: FormulaVars, options?: EvalOptions): FormulaResult;
|
|
101
|
+
/**
|
|
102
|
+
* Static check for the builder: valid syntax, and every referenced identifier is
|
|
103
|
+
* either a known variable or a known function. Returns the unknown names so the
|
|
104
|
+
* UI can flag them.
|
|
105
|
+
*/
|
|
106
|
+
export declare function validateFormula(src: string, knownVars: readonly string[], knownFunctions?: readonly string[]): {
|
|
107
|
+
ok: true;
|
|
108
|
+
variables: string[];
|
|
109
|
+
} | {
|
|
110
|
+
ok: false;
|
|
111
|
+
error: string;
|
|
112
|
+
};
|
|
113
|
+
export {};
|
|
114
|
+
//# sourceMappingURL=formula.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formula.d.ts","sourceRoot":"","sources":["../../src/forms-core/formula.ts"],"names":[],"mappings":"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"}
|