@zhn2605/topo 0.0.0-stage → 0.2.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.
@@ -0,0 +1 @@
1
+ var e=`review`,t=[{nodeId:`src/main.ts#main`,score:.95,reasons:[`package.json bin`,`top-level call main()`]},{nodeId:`src/server/routes.ts#handleCheckout`,score:.6,reasons:[`HTTP route POST /api/checkout`]},{nodeId:`src/checkout.test.ts#testBuy`,score:.3,reasons:[`test entry`]}],n=`acme/shop`,r=JSON.parse('{"nodes":[{"id":"src/main.ts","kind":"file","name":"main.ts","file":"src/main.ts","range":{"startLine":1,"endLine":20},"exported":true,"language":"typescript","tags":[],"mappingStatus":"full"},{"id":"src/store.ts","kind":"file","name":"store.ts","file":"src/store.ts","range":{"startLine":1,"endLine":55},"exported":true,"language":"typescript","tags":[],"mappingStatus":"full"},{"id":"src/products.ts","kind":"file","name":"products.ts","file":"src/products.ts","range":{"startLine":1,"endLine":70},"exported":true,"language":"typescript","tags":[],"mappingStatus":"full"},{"id":"src/checkout.ts","kind":"file","name":"checkout.ts","file":"src/checkout.ts","range":{"startLine":1,"endLine":90},"doc":"Checkout flow: turns a cart into a charged Receipt.\\n\\nPricing is per-currency (see ProductCatalog.price); payment goes through a PaymentGateway so tests can swap in a fake.","exported":true,"language":"typescript","tags":[],"mappingStatus":"full"},{"id":"src/utils/format.ts","kind":"file","name":"format.ts","file":"src/utils/format.ts","range":{"startLine":1,"endLine":15},"doc":"Display helpers for money values. Pure functions, no I/O.","exported":true,"language":"typescript","tags":["util"],"mappingStatus":"full"},{"id":"src/checkout.test.ts","kind":"file","name":"checkout.test.ts","file":"src/checkout.test.ts","range":{"startLine":1,"endLine":30},"exported":false,"language":"typescript","tags":["test"],"mappingStatus":"full"},{"id":"src/main.ts#main","kind":"function","name":"main","parentId":"src/main.ts","file":"src/main.ts","range":{"startLine":5,"endLine":18},"exported":true,"language":"typescript","tags":[],"mappingStatus":"full","signature":"main(): Promise<void>","doc":"Boots the shop: loads the catalog, wires the Stripe gateway and starts the HTTP server on $PORT (default 3000)."},{"id":"src/store.ts#Store","kind":"class","name":"Store","parentId":"src/store.ts","file":"src/store.ts","range":{"startLine":3,"endLine":44},"exported":true,"language":"typescript","tags":[],"mappingStatus":"full","signature":"class Store","doc":"In-memory cart for a single session.\\n\\nNot thread-safe; one Store per request handler."},{"id":"src/store.ts#Store.addToCart","kind":"method","name":"addToCart","parentId":"src/store.ts#Store","file":"src/store.ts","range":{"startLine":10,"endLine":22},"exported":true,"language":"typescript","tags":[],"mappingStatus":"full","signature":"addToCart(productId: string, qty: number): void"},{"id":"src/store.ts#Store.getCart","kind":"method","name":"getCart","parentId":"src/store.ts#Store","file":"src/store.ts","range":{"startLine":24,"endLine":30},"exported":true,"language":"typescript","tags":[],"mappingStatus":"full","signature":"getCart(): CartLine[]"},{"id":"src/products.ts#Product","kind":"interface","name":"Product","parentId":"src/products.ts","file":"src/products.ts","range":{"startLine":1,"endLine":6},"exported":true,"language":"typescript","tags":[],"mappingStatus":"full"},{"id":"src/products.ts#ProductCatalog","kind":"class","name":"ProductCatalog","parentId":"src/products.ts","file":"src/products.ts","range":{"startLine":8,"endLine":58},"exported":true,"language":"typescript","tags":[],"mappingStatus":"full","signature":"class ProductCatalog"},{"id":"src/products.ts#ProductCatalog.find","kind":"method","name":"find","parentId":"src/products.ts#ProductCatalog","file":"src/products.ts","range":{"startLine":12,"endLine":20},"exported":true,"language":"typescript","tags":[],"mappingStatus":"full","signature":"find(id: string): Product | undefined"},{"id":"src/products.ts#ProductCatalog.price","kind":"method","name":"price","parentId":"src/products.ts#ProductCatalog","file":"src/products.ts","range":{"startLine":22,"endLine":34},"exported":true,"language":"typescript","tags":[],"mappingStatus":"full","signature":"price(id: string, currency: Currency): Money","doc":"Price of one unit of a product in the given currency.\\n\\n@param id - product id, as in Product.id\\n@param currency - target currency; must have an exchange rate loaded\\n@returns integer cents in `currency`\\n@throws if the product or the exchange rate is unknown"},{"id":"src/checkout.ts#PaymentGateway","kind":"interface","name":"PaymentGateway","parentId":"src/checkout.ts","file":"src/checkout.ts","range":{"startLine":3,"endLine":6},"exported":true,"language":"typescript","tags":[],"mappingStatus":"full"},{"id":"src/checkout.ts#StripeGateway","kind":"class","name":"StripeGateway","parentId":"src/checkout.ts","file":"src/checkout.ts","range":{"startLine":8,"endLine":20},"exported":true,"language":"typescript","tags":[],"mappingStatus":"full","signature":"class StripeGateway implements PaymentGateway"},{"id":"src/checkout.ts#Checkout","kind":"class","name":"Checkout","parentId":"src/checkout.ts","file":"src/checkout.ts","range":{"startLine":22,"endLine":88},"exported":true,"language":"typescript","tags":[],"mappingStatus":"full","signature":"class Checkout"},{"id":"src/checkout.ts#Checkout.buy","kind":"method","name":"buy","parentId":"src/checkout.ts#Checkout","file":"src/checkout.ts","range":{"startLine":30,"endLine":58},"exported":true,"language":"typescript","tags":[],"mappingStatus":"full","signature":"buy(cart: CartLine[], currency: Currency): Promise<Receipt>","doc":"Charges the cart total and returns a receipt.\\n\\nApplies the session discount code, then charges once via the gateway using an idempotency key derived from the cart, so retries are safe. Clears the cart only after a successful charge.\\n@throws PaymentError when the gateway declines.\\n@throws Error on an empty cart."},{"id":"src/checkout.ts#Checkout.applyDiscount","kind":"method","name":"applyDiscount","parentId":"src/checkout.ts#Checkout","file":"src/checkout.ts","range":{"startLine":60,"endLine":72},"exported":true,"language":"typescript","tags":[],"mappingStatus":"full","signature":"applyDiscount(total: Money, code?: string): Money","doc":"Applies a discount code to a total. Unknown codes are ignored (with a warning) rather than rejected."},{"id":"src/utils/format.ts#formatPrice","kind":"function","name":"formatPrice","parentId":"src/utils/format.ts","file":"src/utils/format.ts","range":{"startLine":1,"endLine":12},"exported":true,"language":"typescript","tags":["util"],"mappingStatus":"partial","signature":"formatPrice(m: Money): string","doc":"Formats money for display using the currency\'s locale, e.g. { cents: 1999, currency: \\"EUR\\" } → \\"19,99 €\\". Negative amounts are shown in parentheses."},{"id":"src/checkout.test.ts#testBuy","kind":"function","name":"testBuy","parentId":"src/checkout.test.ts","file":"src/checkout.test.ts","range":{"startLine":5,"endLine":28},"exported":false,"language":"typescript","tags":["test"],"mappingStatus":"full","signature":"testBuy(): void"},{"id":"src/products.ts#loadCatalog","kind":"function","name":"loadCatalog","file":"src/products.ts","range":{"startLine":60,"endLine":68},"exported":true,"language":"typescript","tags":[],"mappingStatus":"full","signature":"loadCatalog(path: string): Promise<ProductCatalog>","parentId":"src/products.ts","doc":"Reads products.json and the exchange-rate table into a ProductCatalog."},{"id":"src/store.ts#openStore","kind":"function","name":"openStore","file":"src/store.ts","range":{"startLine":46,"endLine":53},"exported":true,"language":"typescript","tags":[],"mappingStatus":"full","signature":"openStore(catalog: ProductCatalog): Store","parentId":"src/store.ts","doc":"Creates the session Store bound to a catalog."},{"id":"src/ui/App.tsx","kind":"file","name":"App.tsx","file":"src/ui/App.tsx","range":{"startLine":1,"endLine":40},"exported":true,"language":"typescript","tags":[],"mappingStatus":"full","doc":"Storefront UI: product list, cart and checkout button."},{"id":"src/ui/App.tsx#App","kind":"function","name":"App","file":"src/ui/App.tsx","range":{"startLine":6,"endLine":38},"exported":true,"language":"typescript","tags":[],"mappingStatus":"full","signature":"App(): JSX.Element","parentId":"src/ui/App.tsx","doc":"Storefront root component; posts the cart to /api/checkout."},{"id":"src/server/routes.ts","kind":"file","name":"routes.ts","file":"src/server/routes.ts","range":{"startLine":1,"endLine":30},"exported":true,"language":"typescript","tags":[],"mappingStatus":"full","doc":"HTTP routes for the storefront."},{"id":"src/server/routes.ts#handleCheckout","kind":"function","name":"handleCheckout","file":"src/server/routes.ts","range":{"startLine":5,"endLine":24},"exported":true,"language":"typescript","tags":[],"mappingStatus":"full","signature":"handleCheckout(req: Request): Promise<Response>","parentId":"src/server/routes.ts","doc":"POST /api/checkout: runs Checkout.buy for the posted cart."}],"edges":[{"id":"src/main.ts#main->calls->src/store.ts#Store.addToCart","from":"src/main.ts#main","to":"src/store.ts#Store.addToCart","kind":"calls","evidence":["static"],"confidence":1,"line":9,"inLoop":true},{"id":"src/main.ts#main->calls->src/checkout.ts#Checkout.buy","from":"src/main.ts#main","to":"src/checkout.ts#Checkout.buy","kind":"calls","evidence":["static"],"confidence":1,"line":11},{"id":"src/main.ts->imports->src/store.ts","from":"src/main.ts","to":"src/store.ts","kind":"imports","evidence":["static"],"confidence":1},{"id":"src/main.ts->imports->src/checkout.ts","from":"src/main.ts","to":"src/checkout.ts","kind":"imports","evidence":["static"],"confidence":1},{"id":"src/store.ts#Store.addToCart->calls->src/products.ts#ProductCatalog.find","from":"src/store.ts#Store.addToCart","to":"src/products.ts#ProductCatalog.find","kind":"calls","evidence":["static","semantic"],"confidence":0.95,"line":12},{"id":"src/store.ts#Store.addToCart->calls->src/products.ts#ProductCatalog.price","from":"src/store.ts#Store.addToCart","to":"src/products.ts#ProductCatalog.price","kind":"calls","evidence":["inferred"],"confidence":0.5,"line":15},{"id":"src/store.ts#Store.getCart->references->src/products.ts#Product","from":"src/store.ts#Store.getCart","to":"src/products.ts#Product","kind":"references","evidence":["static"],"confidence":0.9,"line":26},{"id":"src/store.ts->imports->src/products.ts","from":"src/store.ts","to":"src/products.ts","kind":"imports","evidence":["static"],"confidence":1},{"id":"src/products.ts#ProductCatalog.find->references->src/products.ts#Product","from":"src/products.ts#ProductCatalog.find","to":"src/products.ts#Product","kind":"references","evidence":["static"],"confidence":1,"line":14},{"id":"src/products.ts#ProductCatalog.price->calls->src/utils/format.ts#formatPrice","from":"src/products.ts#ProductCatalog.price","to":"src/utils/format.ts#formatPrice","kind":"calls","evidence":["static"],"confidence":1,"line":32},{"id":"src/products.ts->imports->src/utils/format.ts","from":"src/products.ts","to":"src/utils/format.ts","kind":"imports","evidence":["static"],"confidence":1},{"id":"src/checkout.ts#Checkout.buy->calls->src/products.ts#ProductCatalog.price","from":"src/checkout.ts#Checkout.buy","to":"src/products.ts#ProductCatalog.price","kind":"calls","evidence":["static","semantic"],"confidence":0.95,"line":36,"inLoop":true},{"id":"src/checkout.ts#Checkout.buy->calls->src/store.ts#Store.getCart","from":"src/checkout.ts#Checkout.buy","to":"src/store.ts#Store.getCart","kind":"calls","evidence":["semantic"],"confidence":0.85,"line":31},{"id":"src/checkout.ts#Checkout.buy->references->src/checkout.ts#PaymentGateway","from":"src/checkout.ts#Checkout.buy","to":"src/checkout.ts#PaymentGateway","kind":"references","evidence":["inferred"],"confidence":0.7,"line":41},{"id":"src/checkout.ts#Checkout.buy->calls->src/utils/format.ts#formatPrice","from":"src/checkout.ts#Checkout.buy","to":"src/utils/format.ts#formatPrice","kind":"calls","evidence":["inferred"],"confidence":0.6,"line":55},{"id":"src/checkout.ts#StripeGateway->implements->src/checkout.ts#PaymentGateway","from":"src/checkout.ts#StripeGateway","to":"src/checkout.ts#PaymentGateway","kind":"implements","evidence":["static"],"confidence":1},{"id":"src/checkout.ts->imports->src/products.ts","from":"src/checkout.ts","to":"src/products.ts","kind":"imports","evidence":["static"],"confidence":1},{"id":"src/checkout.ts->imports->src/store.ts","from":"src/checkout.ts","to":"src/store.ts","kind":"imports","evidence":["static"],"confidence":1},{"id":"src/checkout.test.ts#testBuy->calls->src/checkout.ts#Checkout.buy","from":"src/checkout.test.ts#testBuy","to":"src/checkout.ts#Checkout.buy","kind":"calls","evidence":["static"],"confidence":1,"line":12},{"id":"src/checkout.test.ts->imports->src/checkout.ts","from":"src/checkout.test.ts","to":"src/checkout.ts","kind":"imports","evidence":["static"],"confidence":1},{"id":"src/checkout.ts#Checkout.buy->calls->src/checkout.ts#Checkout.applyDiscount","from":"src/checkout.ts#Checkout.buy","to":"src/checkout.ts#Checkout.applyDiscount","kind":"calls","evidence":["static"],"confidence":1,"line":39},{"id":"src/checkout.ts#Checkout.applyDiscount->calls->src/products.ts#ProductCatalog.price","from":"src/checkout.ts#Checkout.applyDiscount","to":"src/products.ts#ProductCatalog.price","kind":"calls","evidence":["static","semantic"],"confidence":0.9,"line":64},{"id":"src/main.ts#main->calls->src/products.ts#loadCatalog","from":"src/main.ts#main","to":"src/products.ts#loadCatalog","kind":"calls","evidence":["static"],"confidence":1.0,"line":6},{"id":"src/main.ts#main->calls->src/store.ts#openStore","from":"src/main.ts#main","to":"src/store.ts#openStore","kind":"calls","evidence":["static"],"confidence":1.0,"line":7},{"id":"src/main.ts#main->references->src/ui/App.tsx#App","from":"src/main.ts#main","to":"src/ui/App.tsx#App","kind":"references","evidence":["inferred"],"confidence":0.6,"line":15,"via":"JSX <App>"},{"id":"src/ui/App.tsx#App->calls->src/server/routes.ts#handleCheckout","from":"src/ui/App.tsx#App","to":"src/server/routes.ts#handleCheckout","kind":"calls","evidence":["inferred"],"confidence":0.5,"line":21,"via":"HTTP POST /api/checkout"},{"id":"src/server/routes.ts#handleCheckout->calls->src/checkout.ts#Checkout.buy","from":"src/server/routes.ts#handleCheckout","to":"src/checkout.ts#Checkout.buy","kind":"calls","evidence":["static","semantic"],"confidence":0.95,"line":12},{"id":"src/products.ts#loadCatalog->references->src/products.ts#ProductCatalog","from":"src/products.ts#loadCatalog","to":"src/products.ts#ProductCatalog","kind":"references","evidence":["static"],"confidence":1.0,"line":66}]}'),i=[{id:`src/checkout.ts#Checkout.legacyTotal`,kind:`method`,name:`legacyTotal`,parentId:`src/checkout.ts#Checkout`,file:`src/checkout.ts`,range:{startLine:74,endLine:86},exported:!0,language:`typescript`,tags:[],mappingStatus:`full`,signature:`legacyTotal(cart: CartLine[]): number`,doc:`@deprecated Sums the cart in USD dollars as a float. Use buy(), which prices per currency in integer cents.`}],a={id:`cs-mock-1`,baseRef:`main`,baseSha:`3f9c2a17e0b4`,headRef:`WORKTREE`,blocks:[{nodeId:`src/products.ts#ProductCatalog.price`,changeType:`signature_changed`,edgesAdded:[`src/checkout.ts#Checkout.applyDiscount->calls->src/products.ts#ProductCatalog.price`],edgesRemoved:[`src/checkout.ts#Checkout.legacyTotal->calls->src/products.ts#ProductCatalog.price`],dependents:5,riskScore:82,riskReasons:[`public signature changed`,`5 transitive dependents`,`called with low confidence (0.50) from Store.addToCart`,`outside its assigned territory`],outOfTerritory:!0,annotationViolations:[],review:`pending`,oldSignature:`price(id: string): number`,newSignature:`price(id: string, currency: Currency): Money`,rationale:`Needed the discount logic here too; didn't want to duplicate it in checkout.`},{nodeId:`src/checkout.ts#Checkout.buy`,changeType:`modified`,edgesAdded:[`src/checkout.ts#Checkout.buy->calls->src/checkout.ts#Checkout.applyDiscount`],edgesRemoved:[`src/checkout.ts#Checkout.buy->calls->src/checkout.ts#Checkout.legacyTotal`],dependents:3,riskScore:64,riskReasons:[`called from entry point main()`,`calls changed: +1 / -1`,`no test changed alongside`],outOfTerritory:!1,annotationViolations:[],review:`pending`,rationale:`Switched to the new discount pipeline so totals match the product page.`},{nodeId:`src/checkout.ts#Checkout.legacyTotal`,changeType:`deleted`,edgesAdded:[],edgesRemoved:[`src/checkout.ts#Checkout.buy->calls->src/checkout.ts#Checkout.legacyTotal`,`src/checkout.ts#Checkout.legacyTotal->calls->src/products.ts#ProductCatalog.price`],dependents:0,riskScore:55,riskReasons:[`deleted method had a caller (Checkout.buy)`,`2 edges removed`],outOfTerritory:!1,annotationViolations:[],review:`pending`},{nodeId:`src/checkout.ts#Checkout.applyDiscount`,changeType:`added`,edgesAdded:[`src/checkout.ts#Checkout.applyDiscount->calls->src/products.ts#ProductCatalog.price`],edgesRemoved:[],dependents:2,riskScore:31,riskReasons:[`new public method`,`calls a changed block (ProductCatalog.price)`],outOfTerritory:!1,annotationViolations:[],review:`pending`},{nodeId:`src/utils/format.ts#formatPrice`,changeType:`modified`,edgesAdded:[],edgesRemoved:[],dependents:3,riskScore:18,riskReasons:[`utility with 2 direct callers`],outOfTerritory:!1,annotationViolations:[],review:`pending`}],edgesAdded:[{id:`src/checkout.ts#Checkout.buy->calls->src/checkout.ts#Checkout.applyDiscount`,from:`src/checkout.ts#Checkout.buy`,to:`src/checkout.ts#Checkout.applyDiscount`,kind:`calls`,evidence:[`static`],confidence:1},{id:`src/checkout.ts#Checkout.applyDiscount->calls->src/products.ts#ProductCatalog.price`,from:`src/checkout.ts#Checkout.applyDiscount`,to:`src/products.ts#ProductCatalog.price`,kind:`calls`,evidence:[`static`,`semantic`],confidence:.9}],edgesRemoved:[{id:`src/checkout.ts#Checkout.buy->calls->src/checkout.ts#Checkout.legacyTotal`,from:`src/checkout.ts#Checkout.buy`,to:`src/checkout.ts#Checkout.legacyTotal`,kind:`calls`,evidence:[`static`],confidence:1},{id:`src/checkout.ts#Checkout.legacyTotal->calls->src/products.ts#ProductCatalog.price`,from:`src/checkout.ts#Checkout.legacyTotal`,to:`src/products.ts#ProductCatalog.price`,kind:`calls`,evidence:[`static`,`semantic`],confidence:.95}],createdAt:`2026-10-07T12:00:00Z`,agentId:`claude`},o={"src/products.ts#ProductCatalog.price":0,"src/checkout.ts#Checkout.buy":0,"src/checkout.ts#Checkout.applyDiscount":0,"src/utils/format.ts#formatPrice":0,"src/store.ts#Store.addToCart":1,"src/main.ts#main":1,"src/checkout.test.ts#testBuy":1,"src/main.ts":2,"src/checkout.test.ts":2,"src/store.ts":2},s=`code -g {file}:{line}`,c=[{id:`checkout`,label:`Checkout`,nodeIds:[`src/checkout.ts`],agent:`claude`,note:`the checkout rewrite`,status:`review`}],l=`agent`,u=[{id:`inbox-1`,kind:`permission`,at:173e10,title:`Claude wants to delete src/checkout.ts#legacyTotal`,detail:`Unused after the discount rewrite; 0 callers left.`,agent:`claude`,label:`Claude · checkout`,territoryId:`checkout`,nodeIds:[`src/checkout.ts#Checkout.legacyTotal`],actions:[`approve`,`deny`,`dismiss`],status:`open`},{id:`inbox-2`,kind:`lens`,at:172999999e4,title:`Claude proposes a view: Discount flow`,detail:`Rooted at ProductCatalog.price, following callees only.`,agent:`claude`,label:`Claude · checkout`,nodeIds:[`src/products.ts#ProductCatalog.price`],lens:{name:`discount-flow`,label:`Discount flow`,description:`ProductCatalog.price and what it calls`,mode:`flow`,roots:[`src/products.ts#ProductCatalog.price`],view:{globalDepth:3,direction:`out`,hopKinds:[`calls`]}},actions:[`approve`,`dismiss`],status:`open`},{id:`inbox-3`,kind:`out_of_territory`,at:17299999e5,title:`Claude edited outside Checkout`,detail:`ProductCatalog.price isn't in the checkout territory.`,agent:`claude`,label:`Claude · checkout`,territoryId:`checkout`,nodeIds:[`src/products.ts#ProductCatalog.price`],actions:[`dismiss`],status:`open`},{id:`inbox-4`,kind:`finished`,at:1729999e6,title:`Claude finished the checkout rewrite`,detail:`5 blocks changed, 1 outside the territory.`,agent:`claude`,label:`Claude · checkout`,runId:`run-1`,territoryId:`checkout`,nodeIds:[`src/checkout.ts#Checkout.buy`],actions:[`dismiss`],status:`approved`}],d=[{id:`run-1`,role:`worker`,territoryId:`checkout`,agent:`claude`,label:`Claude · checkout`,status:`done`,startedAt:1729998e6,endedAt:1729999e6,summary:`Replaced the legacy flat discount with ProductCatalog.price's tiered pricing; left legacyTotal in place pending removal.`,costUsd:.42}],f={mode:e,entryPoints:t,repo:n,head:r,deletedNodes:i,changeSet:a,blastRadius:o,editorCommand:s,territories:c,commandBar:l,inbox:u,runs:d};export{o as blastRadius,a as changeSet,l as commandBar,f as default,i as deletedNodes,s as editorCommand,t as entryPoints,r as head,u as inbox,e as mode,n as repo,d as runs,c as territories};
@@ -0,0 +1,127 @@
1
+ import e from"./review-DZrsjPg6.js";var t=/(\/\/.*)|("(?:\\.|[^"])*"|'(?:\\.|[^'])*'|`(?:\\.|[^`])*`)|\b(\d[\d_.]*n?)\b|\b(as|async|await|break|case|catch|class|const|continue|default|else|export|extends|false|for|from|function|if|import|in|interface|let|new|null|of|private|return|this|throw|true|try|type|typeof|undefined|void|while)\b/g,n=[`comment`,`string`,`number`,`keyword`];function r(e){return e.map(e=>[...e.matchAll(t)].map(e=>{let t=n[e.slice(1).findIndex(e=>e!==void 0)];return[e.index,e.index+e[0].length,t]}))}var i=(e,t)=>Array.from({length:t-e+1},(t,n)=>e+n),a={"head src/products.ts#ProductCatalog.price":{start:22,pre:` }
2
+ `,body:` price(id: string, currency: Currency): Money {
3
+ const product = this.find(id);
4
+ if (!product) {
5
+ throw new Error(\`Unknown product: \${id}\`);
6
+ }
7
+ const rate = this.rates.get(currency);
8
+ if (rate === undefined) {
9
+ throw new Error(\`No exchange rate for \${currency} (loaded: \${[...this.rates.keys()].join(", ")})\`);
10
+ }
11
+ // Prices are stored in USD cents; convert and round half-up.
12
+ const cents = Math.round(product.priceCents * rate);
13
+ return { cents, currency };
14
+ }`,post:`
15
+ listAll(): Product[] {`,changed:[0,...i(5,11)]},"base src/products.ts#ProductCatalog.price":{start:22,pre:` }
16
+ `,body:` price(id: string): number {
17
+ const product = this.find(id);
18
+ if (!product) {
19
+ throw new Error(\`Unknown product: \${id}\`);
20
+ }
21
+ return product.priceCents / 100;
22
+ }`,post:`
23
+ listAll(): Product[] {`,changed:[0,5]},"head src/checkout.ts#Checkout.buy":{start:30,pre:` }
24
+ `,body:` async buy(cart: CartLine[], currency: Currency): Promise<Receipt> {
25
+ if (cart.length === 0) {
26
+ throw new Error("Cannot check out an empty cart");
27
+ }
28
+ let total: Money = { cents: 0, currency };
29
+ for (const line of cart) {
30
+ const unit = this.catalog.price(line.productId, currency);
31
+ total = { cents: total.cents + unit.cents * line.qty, currency };
32
+ }
33
+ total = this.applyDiscount(total, this.discountCode);
34
+
35
+ const charge = await this.gateway.charge({
36
+ amount: total.cents,
37
+ currency: total.currency,
38
+ idempotencyKey: this.idempotencyKey(cart),
39
+ });
40
+ if (charge.status !== "succeeded") {
41
+ throw new PaymentError(charge.failureReason ?? "Payment declined");
42
+ }
43
+
44
+ const receipt: Receipt = {
45
+ id: charge.id,
46
+ lines: cart,
47
+ total,
48
+ paidAt: new Date().toISOString(),
49
+ };
50
+ this.store.clearCart();
51
+ return receipt;
52
+ }`,post:`
53
+ applyDiscount(total: Money, code?: string): Money {`,changed:[...i(4,9),14]},"base src/checkout.ts#Checkout.buy":{start:30,pre:` }
54
+ `,body:` async buy(cart: CartLine[], currency: Currency): Promise<Receipt> {
55
+ if (cart.length === 0) {
56
+ throw new Error("Cannot check out an empty cart");
57
+ }
58
+ const amount = this.legacyTotal(cart);
59
+ const total: Money = { cents: Math.round(amount * 100), currency };
60
+
61
+ const charge = await this.gateway.charge({
62
+ amount: total.cents,
63
+ currency: total.currency,
64
+ });
65
+ if (charge.status !== "succeeded") {
66
+ throw new PaymentError(charge.failureReason ?? "Payment declined");
67
+ }
68
+
69
+ const receipt: Receipt = {
70
+ id: charge.id,
71
+ lines: cart,
72
+ total,
73
+ paidAt: new Date().toISOString(),
74
+ };
75
+ this.store.clearCart();
76
+ return receipt;
77
+ }`,post:`
78
+ legacyTotal(cart: CartLine[]): number {`,changed:[4,5]},"head src/checkout.ts#Checkout.applyDiscount":{start:60,pre:` }
79
+ `,body:` applyDiscount(total: Money, code?: string): Money {
80
+ if (!code) {
81
+ return total;
82
+ }
83
+ const pct = DISCOUNTS[code.toUpperCase()];
84
+ if (pct === undefined) {
85
+ console.warn(\`Ignoring unknown discount code \${code}\`);
86
+ return total;
87
+ }
88
+ // Round in the customer's favour so totals never exceed the quote.
89
+ const cents = Math.floor(total.cents * (1 - pct / 100));
90
+ return { cents, currency: total.currency };
91
+ }`,post:`
92
+ private idempotencyKey(cart: CartLine[]): string {`,changed:i(0,12)},"base src/checkout.ts#Checkout.legacyTotal":{start:74,pre:` }
93
+ `,body:` legacyTotal(cart: CartLine[]): number {
94
+ let sum = 0;
95
+ for (const line of cart) {
96
+ const unit = this.catalog.price(line.productId);
97
+ if (unit === undefined) continue;
98
+ sum += unit * line.qty;
99
+ }
100
+ if (this.discountCode === "WELCOME10") {
101
+ sum *= 0.9;
102
+ }
103
+ // Float dollars; callers multiply by 100 again.
104
+ return Math.round(sum * 100) / 100;
105
+ }`,post:`}`,changed:i(0,12)},"head src/utils/format.ts#formatPrice":{start:1,body:`export function formatPrice(m: Money): string {
106
+ const fmt = new Intl.NumberFormat(LOCALES[m.currency] ?? "en-US", {
107
+ style: "currency",
108
+ currency: m.currency,
109
+ minimumFractionDigits: 2,
110
+ });
111
+ const text = fmt.format(Math.abs(m.cents) / 100);
112
+ if (m.cents < 0) {
113
+ return \`(\${text})\`;
114
+ }
115
+ return text;
116
+ }`,post:`
117
+ const LOCALES: Partial<Record<Currency, string>> = {`,changed:i(1,10)},"base src/utils/format.ts#formatPrice":{start:1,body:`export function formatPrice(m: Money): string {
118
+ const sign = m.cents < 0 ? "-" : "";
119
+ const abs = Math.abs(m.cents);
120
+ const units = Math.floor(abs / 100);
121
+ const cents = String(abs % 100).padStart(2, "0");
122
+ return \`\${sign}\${m.currency} \${units}.\${cents}\`;
123
+ }`,post:``,changed:i(1,5)}},o=e,s=new Map([...o.head.nodes,...o.deletedNodes].map(e=>[e.id,e])),c=e=>e.kind===`function`?`export function ${e.signature??`${e.name}()`}`:e.kind===`method`?` ${e.signature??`${e.name}()`}`:`export ${e.signature??`${e.kind} ${e.name}`}`;function l(e){if(e.kind===`file`){let t=o.head.nodes.filter(t=>t.parentId===e.id).map(e=>`${c(e)} { … }`).join(`
124
+ `);return{start:e.range.startLine,body:t||`// (empty module)`,changed:[]}}let t=e.kind===`method`?` `:``;return{start:e.range.startLine,body:`${c(e)} {\n${t} // …`,changed:[]}}function u(e,t){let n=s.get(e);if(!n)return null;let i=a[`${t} ${e}`]??(t===`head`?l(n):null);if(!i)return null;let o=i.pre?i.pre.split(`
125
+ `):[],c=i.body.split(`
126
+ `),u=a[`${t} ${e}`]?i.start+c.length-1:n.range.endLine,d=[...o,...c,...i.post?i.post.split(`
127
+ `):[]];return{nodeId:e,side:t,file:n.file,startLine:i.start-o.length,lines:d,block:{startLine:i.start,endLine:u},changedLines:i.changed.map(e=>i.start+e),tokens:r(d)}}export{u as mockSource};
@@ -0,0 +1 @@
1
+ function e(e,t){let n=new Map(e.head.nodes.map(e=>[e.id,e])),r=e=>e.tags.some(e=>t.hiddenTags.includes(e)),i=new Map,a=(e,t)=>i.set(e,[...i.get(e)??[],t]);for(let n of e.head.edges)t.hopKinds.includes(n.kind)&&(t.direction!==`in`&&a(n.from,n.to),t.direction!==`out`&&a(n.to,n.from));let o={},s=new Map,c=t.rootNodeIds.filter(e=>n.has(e)).map(e=>[e,t.branchOverrides[e]??t.globalDepth,0]);for(;c.length;){let[e,a,l]=c.shift();if((s.get(e)??-1)>=a&&e in o)continue;s.set(e,a),o[e]=Math.min(o[e]??l,l);let u=t.branchOverrides[e]??a;if(!(u<=0))for(let a of i.get(e)??[]){let e=n.get(a);e&&!r(e)&&c.push([a,t.branchOverrides[a]??u-1,l+1])}}let l=new Set(Object.keys(o));for(let e of[...l])for(let t=n.get(e)?.parentId;t;t=n.get(t)?.parentId)l.add(t);return{nodes:e.head.nodes.filter(e=>l.has(e.id)),edges:e.head.edges.filter(e=>l.has(e.from)&&l.has(e.to)&&t.hopKinds.includes(e.kind)),distance:o}}export{e as mockView};
@@ -0,0 +1,13 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Topo review</title>
7
+ <script type="module" crossorigin src="/assets/index-IpMwIh-N.js"></script>
8
+ <link rel="stylesheet" crossorigin href="/assets/index-51XzhJVO.css">
9
+ </head>
10
+ <body>
11
+ <div id="root"></div>
12
+ </body>
13
+ </html>