@bowmark/web 1.0.0 → 1.1.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 CHANGED
@@ -1,11 +1,12 @@
1
1
  # @bowmark/web
2
2
 
3
- > **Status:** publishable, 2026-08-05 · `private` is gone and the two-hop release is
4
- > wired (Phase 6 of
5
- > [`docs/plans/public-types-package.md`](../../../docs/plans/public-types-package.md)).
6
- > Nothing above `0.0.0` is on npm until release-please bumps `package.json` and the
7
- > mirror's `publish.yml` sees the change. **What would make this doc wrong:** a build
8
- > step appearing, or the declarations moving out into a second package.
3
+ > **Status:** PUBLISHED · `@bowmark/web@1.0.0` on npm, 2026-08-06, alongside
4
+ > `bowmark-web` and `bowmark-web-stubs` on PyPI at the same version. The plan that built it
5
+ > is deleted; the reasoning is in the four
6
+ > [`docs/decisions/2026-08-06-*`](../../../docs/decisions/) records and the enforceable half
7
+ > is [`.claude/rules/public-types.md`](../../../.claude/rules/public-types.md).
8
+ > **What would make this doc wrong:** a build step appearing, the declarations moving out
9
+ > into a second package, or a runtime dependency landing in `package.json`.
9
10
 
10
11
  ```sh
11
12
  npm i @bowmark/web
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bowmark/web",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "type": "module",
5
5
  "description": "The public client for the Bowmark capability library — real TypeScript for the whole bowmark.* surface, with no Bowmark source on the caller's disk. ZERO runtime dependencies, deliberately and permanently.",
6
6
  "license": "MIT",
@@ -5,8 +5,8 @@
5
5
  // rather than imported. An `import` or `export` at the top level of this file would
6
6
  // turn it into a module and every declaration below would stop being global.
7
7
  //
8
- // Manifest version: f5800ce1b32bab70e47d10acdfdc561ee2a242f65b2af263ba4dd9fe109e55e9
9
- // 8 capabilities, 67 providers, 199 typed functions, 20 refused.
8
+ // Manifest version: 11b1a109d7e69ffbbcccb30182dd5333770aeb23ab75946f15d55d7f7d84a7bf
9
+ // 8 capabilities, 68 providers, 202 typed functions, 20 refused.
10
10
  //
11
11
  // REFUSED — these functions are real and callable, and their declared arguments
12
12
  // carry no types, so no honest signature exists. Each one is commented in place
@@ -1680,6 +1680,100 @@ interface KayakCar {
1680
1680
  }
1681
1681
  }
1682
1682
 
1683
+ declare namespace BowmarkProvider_chriscraft {
1684
+ // ── Chris-Craft — the unit's own declarations, verbatim ──
1685
+ // Chris-Craft's OWN shapes — not a capability contract.
1686
+
1687
+ type ChriscraftBoatType = "STERNDRIVE" | "OUTBOARD" | "SURF";
1688
+
1689
+ interface ChriscraftModelSummary { modelId: string; boatType: ChriscraftBoatType; name: string; url: string }
1690
+
1691
+ interface ChriscraftOptionChoice {
1692
+ id: string; // the site's own guid
1693
+ name: string;
1694
+ price: number; // MSRP delta, 0 for a no-charge default
1695
+ priceFormatted: string;
1696
+ discountPercentage: number;
1697
+ yourPrice: number; // discounted price, ROUNDED per choice (matches the site's own display)
1698
+ yourPriceFormatted: string;
1699
+ isDefault: boolean; // true if the page loads with this choice already picked
1700
+ }
1701
+
1702
+ interface ChriscraftOptionGroup {
1703
+ category: string; // broader section, e.g. "Edition Selection", "Paint"
1704
+ group: string; // the key priceConfiguration's selections are matched against
1705
+ required: boolean; // true for a mandatory group (Edition Selection, Engine Type)
1706
+ maxSelections: number | null; // 1 = single-select, null = unlimited multi-select (e.g. Additional Options)
1707
+ choices: ChriscraftOptionChoice[];
1708
+ }
1709
+
1710
+ interface ChriscraftConfigurator {
1711
+ modelId: string;
1712
+ boatType: ChriscraftBoatType;
1713
+ name: string;
1714
+ url: string;
1715
+ groups: ChriscraftOptionGroup[];
1716
+ }
1717
+
1718
+ interface ChriscraftPriceLine { group: string; choice: string; price: number; yourPrice: number }
1719
+
1720
+ interface ChriscraftPriceResult {
1721
+ modelId: string;
1722
+ boatType: ChriscraftBoatType;
1723
+ msrpTotal: number;
1724
+ msrpTotalFormatted: string;
1725
+ yourPriceTotal: number;
1726
+ yourPriceTotalFormatted: string;
1727
+ breakdown: ChriscraftPriceLine[]; // one line per group — the caller's pick(s), or the site's own default
1728
+ unmatched: string[]; // a caller selection that matched no real group/choice
1729
+ unresolvedGroups: string[]; // a REQUIRED group with no pick and no default (e.g. Edition Selection, Engine Type) — totals are a FLOOR until these are picked
1730
+ handoffUrl: string; // the model's own builder page — no shareable configured-state URL exists to build, and the aggregate total is behind a lead-capture form never submitted here
1731
+ }
1732
+
1733
+ /**
1734
+ * Chris-Craft's runabout 'Build Your Own' product builder — list every current model and boat
1735
+ * type, read one build's full option tree (edition, engine, hull/stripe/vinyl colors, ~29
1736
+ * named accessories, cover, flooring and more, each choice's exact MSRP and discounted Your
1737
+ * Price), and price a specific build against the site's own live pricing rather than a
1738
+ * researched estimate.
1739
+ */
1740
+ interface Unit {
1741
+ /**
1742
+ * Lists every current Chris-Craft model+boat-type combination from the public "Build Your Own"
1743
+ * gallery — model id, boat type (STERNDRIVE/OUTBOARD/SURF), name and its build.chriscraft.com
1744
+ * builder URL. `query` (optional) narrows the list by a case-insensitive substring match on
1745
+ * the name, e.g. "sportster". The `modelId`/`boatType` pair on each row is what
1746
+ * getConfigurator and priceConfiguration take.
1747
+ */
1748
+ searchModels(query?: string): Promise<ChriscraftModelSummary[]>;
1749
+
1750
+ /**
1751
+ * Reads one model+boat-type's whole builder: every option group (Edition Selection, Top
1752
+ * Option, Engine Type, Hull Color, Stripe Color, Cockpit Vinyl colors, Contrast Stitching,
1753
+ * Additional Options and more — the exact set varies by model) with each choice's exact name,
1754
+ * MSRP, discounted Your Price, whether the group is required, how many choices it allows, and
1755
+ * whether a choice is the default. THROWS on an unknown (modelId, boatType) pair, naming
1756
+ * searchModels() as the way to find current ones.
1757
+ */
1758
+ getConfigurator(modelId: string, boatType: ChriscraftBoatType): Promise<ChriscraftConfigurator>;
1759
+
1760
+ /**
1761
+ * Prices ONE specific build — selections keyed by option group (case-insensitive), a single
1762
+ * choice name or, for a multi-select group like "Additional Options", an array of choice
1763
+ * names, e.g. { "Edition Selection": "Standard Edition", "Engine Type": "Volvo V8 5.3L (300HP)
1764
+ * DP FWC EVC", "Additional Options": ["Bow Filler Cushion"] } — against the model's live
1765
+ * builder and returns the MSRP total, the discounted Your Price total, the per-group
1766
+ * breakdown, and the model's own builder URL (Chris-Craft publishes no shareable URL for a
1767
+ * configured state, and the aggregate "View My Build" total sits behind a lead-capture form
1768
+ * this function never submits). `unresolvedGroups` names any REQUIRED group with neither a
1769
+ * caller pick nor a site default (Edition Selection, Engine Type) — both totals are a FLOOR
1770
+ * until those are chosen. `unmatched` names any selection that matched no real group or
1771
+ * choice, rather than silently mispricing.
1772
+ */
1773
+ priceConfiguration(modelId: string, boatType: ChriscraftBoatType, selections: Record<string, string | string[]>): Promise<ChriscraftPriceResult>;
1774
+ }
1775
+ }
1776
+
1683
1777
  declare namespace BowmarkProvider_classpass {
1684
1778
  // ── ClassPass — the unit's own declarations, verbatim ──
1685
1779
  interface ClasspassSchedule {
@@ -10318,6 +10412,7 @@ interface BowmarkProviders {
10318
10412
  bmwusa: BowmarkProvider_bmwusa.Unit;
10319
10413
  cars: BowmarkProvider_cars.Unit;
10320
10414
  cheapflights: BowmarkProvider_cheapflights.Unit;
10415
+ chriscraft: BowmarkProvider_chriscraft.Unit;
10321
10416
  classpass: BowmarkProvider_classpass.Unit;
10322
10417
  cloudflare: BowmarkProvider_cloudflare.Unit;
10323
10418
  dickssportinggoods: BowmarkProvider_dickssportinggoods.Unit;
@@ -5,13 +5,13 @@
5
5
  // declares no readable argument shape — not an absent one, which is what the
6
6
  // guard fails closed on.
7
7
  //
8
- // Manifest version: f5800ce1b32bab70e47d10acdfdc561ee2a242f65b2af263ba4dd9fe109e55e9
9
- // 199 checked, 20 unchecked.
8
+ // Manifest version: 11b1a109d7e69ffbbcccb30182dd5333770aeb23ab75946f15d55d7f7d84a7bf
9
+ // 202 checked, 20 unchecked.
10
10
 
11
11
  import type { ValidatorTable } from "../validate.js";
12
12
 
13
13
  export const VALIDATORS: ValidatorTable = {
14
- "version": "f5800ce1b32bab70e47d10acdfdc561ee2a242f65b2af263ba4dd9fe109e55e9",
14
+ "version": "11b1a109d7e69ffbbcccb30182dd5333770aeb23ab75946f15d55d7f7d84a7bf",
15
15
  "units": {
16
16
  "cars": {
17
17
  "defs": {
@@ -1990,6 +1990,93 @@ export const VALIDATORS: ValidatorTable = {
1990
1990
  ]
1991
1991
  }
1992
1992
  },
1993
+ "providers.chriscraft": {
1994
+ "defs": {
1995
+ "ChriscraftBoatType": {
1996
+ "k": "union",
1997
+ "of": [
1998
+ {
1999
+ "k": "literal",
2000
+ "v": "STERNDRIVE"
2001
+ },
2002
+ {
2003
+ "k": "literal",
2004
+ "v": "OUTBOARD"
2005
+ },
2006
+ {
2007
+ "k": "literal",
2008
+ "v": "SURF"
2009
+ }
2010
+ ]
2011
+ }
2012
+ },
2013
+ "functions": {
2014
+ "searchModels": [
2015
+ {
2016
+ "name": "query",
2017
+ "schema": {
2018
+ "k": "string"
2019
+ },
2020
+ "optional": true
2021
+ }
2022
+ ],
2023
+ "getConfigurator": [
2024
+ {
2025
+ "name": "modelId",
2026
+ "schema": {
2027
+ "k": "string"
2028
+ },
2029
+ "optional": false
2030
+ },
2031
+ {
2032
+ "name": "boatType",
2033
+ "schema": {
2034
+ "k": "ref",
2035
+ "name": "ChriscraftBoatType"
2036
+ },
2037
+ "optional": false
2038
+ }
2039
+ ],
2040
+ "priceConfiguration": [
2041
+ {
2042
+ "name": "modelId",
2043
+ "schema": {
2044
+ "k": "string"
2045
+ },
2046
+ "optional": false
2047
+ },
2048
+ {
2049
+ "name": "boatType",
2050
+ "schema": {
2051
+ "k": "ref",
2052
+ "name": "ChriscraftBoatType"
2053
+ },
2054
+ "optional": false
2055
+ },
2056
+ {
2057
+ "name": "selections",
2058
+ "schema": {
2059
+ "k": "record",
2060
+ "value": {
2061
+ "k": "union",
2062
+ "of": [
2063
+ {
2064
+ "k": "string"
2065
+ },
2066
+ {
2067
+ "k": "array",
2068
+ "of": {
2069
+ "k": "string"
2070
+ }
2071
+ }
2072
+ ]
2073
+ }
2074
+ },
2075
+ "optional": false
2076
+ }
2077
+ ]
2078
+ }
2079
+ },
1993
2080
  "providers.classpass": {
1994
2081
  "defs": {
1995
2082
  "ClasspassScheduleOptions": {
package/src/index.ts CHANGED
@@ -7,8 +7,7 @@
7
7
  // imported. An `import` of them would make them a module and every global below
8
8
  // would stop resolving. They ship INSIDE this package rather than beside it —
9
9
  // `npm i @bowmark/web` and nothing else is the promise, and it is what the
10
- // acceptance criteria are written against (`docs/plans/public-types-package.md`
11
- // → One package, not two).
10
+ // acceptance criteria are written against (`docs/decisions/2026-08-06-the-public-client-is-one-manifest-two-languages.md`).
12
11
  //
13
12
  // ── The same declarations describe TWO implementations, deliberately ──
14
13
  //