@fayz-ai/shop 0.9.0 → 0.11.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 (163) hide show
  1. package/README.md +18 -1
  2. package/dist/admin.d.ts +2 -0
  3. package/dist/admin.d.ts.map +1 -0
  4. package/dist/catalog.d.ts +1 -3
  5. package/dist/catalog.d.ts.map +1 -1
  6. package/dist/catalog.js +2 -2
  7. package/dist/{chunk-IYQHKMLB.js → chunk-2WACO2TG.js} +4 -4
  8. package/dist/chunk-2WACO2TG.js.map +1 -0
  9. package/dist/chunk-3GERSY5F.js +526 -0
  10. package/dist/chunk-3GERSY5F.js.map +1 -0
  11. package/dist/chunk-6BO2TMZ5.js +93 -0
  12. package/dist/chunk-6BO2TMZ5.js.map +1 -0
  13. package/dist/chunk-FQPGE3YN.js +3 -0
  14. package/dist/{chunk-JR25TISO.js.map → chunk-FQPGE3YN.js.map} +1 -1
  15. package/dist/{chunk-CTKZ6O2J.js → chunk-IKNGCRUM.js} +41 -15
  16. package/dist/chunk-IKNGCRUM.js.map +1 -0
  17. package/dist/chunk-KLDS7IPU.js +17 -0
  18. package/dist/chunk-KLDS7IPU.js.map +1 -0
  19. package/dist/chunk-NWW3WJ7Y.js +136 -0
  20. package/dist/chunk-NWW3WJ7Y.js.map +1 -0
  21. package/dist/chunk-STRNMFC4.js +1438 -0
  22. package/dist/chunk-STRNMFC4.js.map +1 -0
  23. package/dist/chunk-U6HV3LVP.js +1170 -0
  24. package/dist/chunk-U6HV3LVP.js.map +1 -0
  25. package/dist/client.d.ts +2 -0
  26. package/dist/client.d.ts.map +1 -0
  27. package/dist/data/customer-search.d.ts +3 -0
  28. package/dist/data/customer-search.d.ts.map +1 -0
  29. package/dist/data/functions.d.ts +9 -0
  30. package/dist/data/functions.d.ts.map +1 -0
  31. package/dist/data/media.d.ts +37 -0
  32. package/dist/data/media.d.ts.map +1 -0
  33. package/dist/{mock-catalog.d.ts → data/mock-catalog.d.ts} +21 -1
  34. package/dist/data/mock-catalog.d.ts.map +1 -0
  35. package/dist/data/mock-provider.d.ts +165 -0
  36. package/dist/data/mock-provider.d.ts.map +1 -0
  37. package/dist/data/mock.d.ts +3 -0
  38. package/dist/data/mock.d.ts.map +1 -0
  39. package/dist/data/provider.d.ts +335 -0
  40. package/dist/data/provider.d.ts.map +1 -0
  41. package/dist/data/supabase-provider.d.ts +208 -0
  42. package/dist/data/supabase-provider.d.ts.map +1 -0
  43. package/dist/data/tables.d.ts +38 -0
  44. package/dist/data/tables.d.ts.map +1 -0
  45. package/dist/data/tenant.d.ts.map +1 -0
  46. package/dist/entities/entity-reconcile.d.ts +32 -0
  47. package/dist/entities/entity-reconcile.d.ts.map +1 -0
  48. package/dist/entities/entity-sql.d.ts +50 -0
  49. package/dist/entities/entity-sql.d.ts.map +1 -0
  50. package/dist/entities/entity-store.d.ts +58 -0
  51. package/dist/entities/entity-store.d.ts.map +1 -0
  52. package/dist/entities/index.d.ts +10 -0
  53. package/dist/entities/index.d.ts.map +1 -0
  54. package/dist/entities/mock-entity-store.d.ts +17 -0
  55. package/dist/entities/mock-entity-store.d.ts.map +1 -0
  56. package/dist/entities/supabase-entity-store.d.ts +8 -0
  57. package/dist/entities/supabase-entity-store.d.ts.map +1 -0
  58. package/dist/entities.js +159 -0
  59. package/dist/entities.js.map +1 -0
  60. package/dist/index.d.ts +28 -12
  61. package/dist/index.d.ts.map +1 -1
  62. package/dist/index.js +1558 -40
  63. package/dist/index.js.map +1 -1
  64. package/dist/inventory/allocation.d.ts +98 -0
  65. package/dist/inventory/allocation.d.ts.map +1 -0
  66. package/dist/inventory/index.d.ts +13 -0
  67. package/dist/inventory/index.d.ts.map +1 -0
  68. package/dist/inventory/mock-stock-store.d.ts +89 -0
  69. package/dist/inventory/mock-stock-store.d.ts.map +1 -0
  70. package/dist/inventory/postgrest-double.d.ts +65 -0
  71. package/dist/inventory/postgrest-double.d.ts.map +1 -0
  72. package/dist/inventory/shopify-mapping.d.ts +67 -0
  73. package/dist/inventory/shopify-mapping.d.ts.map +1 -0
  74. package/dist/inventory/stock-contract.d.ts +46 -0
  75. package/dist/inventory/stock-contract.d.ts.map +1 -0
  76. package/dist/inventory/stock-store.d.ts +96 -0
  77. package/dist/inventory/stock-store.d.ts.map +1 -0
  78. package/dist/inventory/stock-types.d.ts +351 -0
  79. package/dist/inventory/stock-types.d.ts.map +1 -0
  80. package/dist/inventory/supabase-stock-store.d.ts +60 -0
  81. package/dist/inventory/supabase-stock-store.d.ts.map +1 -0
  82. package/dist/inventory/vocabulary.d.ts +86 -0
  83. package/dist/inventory/vocabulary.d.ts.map +1 -0
  84. package/dist/inventory.js +4 -0
  85. package/dist/inventory.js.map +1 -0
  86. package/dist/lib/catalog.d.ts +4 -0
  87. package/dist/lib/catalog.d.ts.map +1 -0
  88. package/dist/{commerce.d.ts → lib/commerce.d.ts} +2 -2
  89. package/dist/lib/commerce.d.ts.map +1 -0
  90. package/dist/lib/document.d.ts +13 -0
  91. package/dist/lib/document.d.ts.map +1 -0
  92. package/dist/lib/emails.d.ts +50 -0
  93. package/dist/lib/emails.d.ts.map +1 -0
  94. package/dist/lib/message-events.d.ts +4 -0
  95. package/dist/lib/message-events.d.ts.map +1 -0
  96. package/dist/lib/runtime.d.ts +5 -0
  97. package/dist/lib/runtime.d.ts.map +1 -0
  98. package/dist/lib/variant-matrix.d.ts +120 -0
  99. package/dist/lib/variant-matrix.d.ts.map +1 -0
  100. package/dist/mock.d.ts +1 -2
  101. package/dist/mock.d.ts.map +1 -1
  102. package/dist/mock.js +4 -2
  103. package/dist/provider.d.ts +1 -88
  104. package/dist/provider.d.ts.map +1 -1
  105. package/dist/providers/checkout.d.ts +129 -0
  106. package/dist/providers/checkout.d.ts.map +1 -0
  107. package/dist/providers/index.d.ts +5 -0
  108. package/dist/providers/index.d.ts.map +1 -0
  109. package/dist/providers/shipping.d.ts +43 -0
  110. package/dist/providers/shipping.d.ts.map +1 -0
  111. package/dist/providers.js +70 -0
  112. package/dist/providers.js.map +1 -0
  113. package/dist/rules/adapter.d.ts +36 -0
  114. package/dist/rules/adapter.d.ts.map +1 -0
  115. package/dist/rules/attributes.d.ts +64 -0
  116. package/dist/rules/attributes.d.ts.map +1 -0
  117. package/dist/rules/context.d.ts +43 -0
  118. package/dist/rules/context.d.ts.map +1 -0
  119. package/dist/rules/evaluator.d.ts +37 -0
  120. package/dist/rules/evaluator.d.ts.map +1 -0
  121. package/dist/rules/index.d.ts +13 -0
  122. package/dist/rules/index.d.ts.map +1 -0
  123. package/dist/rules/prices.d.ts +25 -0
  124. package/dist/rules/prices.d.ts.map +1 -0
  125. package/dist/rules/rule-types.d.ts +160 -0
  126. package/dist/rules/rule-types.d.ts.map +1 -0
  127. package/dist/rules.js +22 -0
  128. package/dist/rules.js.map +1 -0
  129. package/dist/runtime.d.ts +1 -4
  130. package/dist/runtime.d.ts.map +1 -1
  131. package/dist/runtime.js +5 -3
  132. package/dist/shipping/label-provider.d.ts +43 -0
  133. package/dist/shipping/label-provider.d.ts.map +1 -0
  134. package/dist/types.d.ts +688 -0
  135. package/dist/types.d.ts.map +1 -1
  136. package/package.json +30 -20
  137. package/dist/chunk-CTKZ6O2J.js.map +0 -1
  138. package/dist/chunk-IYQHKMLB.js.map +0 -1
  139. package/dist/chunk-JR25TISO.js +0 -3
  140. package/dist/chunk-SVTCJ6HP.js +0 -440
  141. package/dist/chunk-SVTCJ6HP.js.map +0 -1
  142. package/dist/commerce.d.ts.map +0 -1
  143. package/dist/mock-catalog.d.ts.map +0 -1
  144. package/dist/mock-provider.d.ts +0 -60
  145. package/dist/mock-provider.d.ts.map +0 -1
  146. package/dist/supabase-provider.d.ts +0 -56
  147. package/dist/supabase-provider.d.ts.map +0 -1
  148. package/dist/tables.d.ts +0 -12
  149. package/dist/tables.d.ts.map +0 -1
  150. package/dist/tenant.d.ts.map +0 -1
  151. package/src/catalog.ts +0 -3
  152. package/src/commerce.ts +0 -120
  153. package/src/index.ts +0 -40
  154. package/src/mock-catalog.ts +0 -266
  155. package/src/mock-provider.ts +0 -480
  156. package/src/mock.ts +0 -2
  157. package/src/provider.ts +0 -117
  158. package/src/runtime.ts +0 -20
  159. package/src/supabase-provider.ts +0 -754
  160. package/src/tables.ts +0 -17
  161. package/src/tenant.ts +0 -21
  162. package/src/types.ts +0 -623
  163. /package/dist/{tenant.d.ts → data/tenant.d.ts} +0 -0
@@ -0,0 +1,64 @@
1
+ import { Registry } from '@fayz-ai/core';
2
+ import type { RegistryMeta } from '@fayz-ai/core';
3
+ import type { RuleOperator } from './rule-types';
4
+ export declare const RULE_ATTRIBUTE_FIELD_TYPES: readonly ["text", "number", "boolean"];
5
+ export type RuleAttributeFieldType = (typeof RULE_ATTRIBUTE_FIELD_TYPES)[number];
6
+ /**
7
+ * One vocabulary row.
8
+ *
9
+ * `path` locates the value in the evaluation context built from the cart
10
+ * snapshot. Paths under `items.` are ITEM-scoped: they evaluate per cart line
11
+ * (scoping target/buy rules to lines; for eligibility, "some line matches").
12
+ * Every other path is CART-scoped, walked from the snapshot root. A context
13
+ * provider's attributes resolve by KEY from the provided context instead.
14
+ *
15
+ * `value_source` names the id list an admin form offers as values
16
+ * ('products', 'categories', …) — a UI hint, never an evaluation input.
17
+ */
18
+ export interface RuleAttribute {
19
+ key: string;
20
+ path: string;
21
+ label: string;
22
+ fieldType: RuleAttributeFieldType;
23
+ /** Where an admin form fetches candidate values. Null = free entry. */
24
+ valueSource?: string | null;
25
+ /** The operators this attribute supports — a subset of the 7. */
26
+ operators: readonly RuleOperator[];
27
+ }
28
+ /** Prefix that marks an attribute path as item-scoped. */
29
+ export declare const ITEM_PATH_PREFIX = "items.";
30
+ /**
31
+ * The core vocabulary — what every Fayz-backed store starts with, mirrored as
32
+ * the plg_shop_rule_attributes seed rows in migration 0032.
33
+ */
34
+ export declare const CORE_RULE_ATTRIBUTES: readonly RuleAttribute[];
35
+ export declare const ruleAttributeRegistry: Registry<RuleAttribute>;
36
+ /** Idempotent — mirrors registerStorefrontBlocks: consumers call before reads. */
37
+ export declare function registerCoreRuleAttributes(): void;
38
+ export interface RegisterRuleAttributeOptions {
39
+ meta?: RegistryMeta;
40
+ /** Re-registering an existing key is an error unless the caller owns it
41
+ * (module re-evaluation under HMR re-registers the same declaration). */
42
+ replace?: boolean;
43
+ }
44
+ /**
45
+ * Widen the vocabulary with one attribute. Duplicate keys are an I2 hard
46
+ * error naming the taken set — two providers silently fighting over one key
47
+ * would make rules mean different things on different renders.
48
+ */
49
+ export declare function registerRuleAttribute(attribute: RuleAttribute, options?: RegisterRuleAttributeOptions): void;
50
+ /** The attribute for a key, or an I2 hard error naming the valid set — the
51
+ * only lookup the evaluator and the validators may use. */
52
+ export declare function resolveRuleAttribute(key: string): RuleAttribute;
53
+ export declare function hasRuleAttribute(key: string): boolean;
54
+ /** Every attribute key, sorted — the valid set I2 errors name. */
55
+ export declare function listRuleAttributeKeys(): string[];
56
+ /** Every vocabulary row, sorted by key — what describeStore publishes and the
57
+ * admin promotion form renders itself from. */
58
+ export declare function listRuleAttributes(): RuleAttribute[];
59
+ /** True when the attribute evaluates per cart line. */
60
+ export declare function isItemScopedAttribute(attribute: RuleAttribute): boolean;
61
+ /** Test seam — suites that widen the vocabulary must not leak into the next.
62
+ * Core attributes re-register on the next read. */
63
+ export declare function clearRuleAttributes(): void;
64
+ //# sourceMappingURL=attributes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attributes.d.ts","sourceRoot":"","sources":["../../src/rules/attributes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACxC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAEjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAqBhD,eAAO,MAAM,0BAA0B,wCAAyC,CAAA;AAChF,MAAM,MAAM,sBAAsB,GAAG,CAAC,OAAO,0BAA0B,CAAC,CAAC,MAAM,CAAC,CAAA;AAEhF;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,EAAE,sBAAsB,CAAA;IACjC,uEAAuE;IACvE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,iEAAiE;IACjE,SAAS,EAAE,SAAS,YAAY,EAAE,CAAA;CACnC;AAKD,0DAA0D;AAC1D,eAAO,MAAM,gBAAgB,WAAW,CAAA;AAExC;;;GAGG;AACH,eAAO,MAAM,oBAAoB,EAAE,SAAS,aAAa,EAyExD,CAAA;AAOD,eAAO,MAAM,qBAAqB,yBAA+C,CAAA;AAIjF,kFAAkF;AAClF,wBAAgB,0BAA0B,IAAI,IAAI,CAUjD;AAED,MAAM,WAAW,4BAA4B;IAC3C,IAAI,CAAC,EAAE,YAAY,CAAA;IACnB;8EAC0E;IAC1E,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,aAAa,EAAE,OAAO,GAAE,4BAAiC,GAAG,IAAI,CA6BhH;AAED;4DAC4D;AAC5D,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,CAO/D;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAGrD;AAED,kEAAkE;AAClE,wBAAgB,qBAAqB,IAAI,MAAM,EAAE,CAGhD;AAED;gDACgD;AAChD,wBAAgB,kBAAkB,IAAI,aAAa,EAAE,CAMpD;AAED,uDAAuD;AACvD,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,aAAa,GAAG,OAAO,CAEvE;AAED;oDACoD;AACpD,wBAAgB,mBAAmB,IAAI,IAAI,CAG1C"}
@@ -0,0 +1,43 @@
1
+ import { Registry } from '@fayz-ai/core';
2
+ import type { RegistryMeta } from '@fayz-ai/core';
3
+ import type { RuleAttribute } from './attributes';
4
+ import type { RuleCartSnapshot } from './rule-types';
5
+ /** What a provider contributes: one context value per declared attribute key.
6
+ * A value may be a scalar of the declared field type or an array of them
7
+ * (e.g. customer tags); null/undefined mean "no value" and are dropped. */
8
+ export type RuleContext = Record<string, unknown>;
9
+ export interface RuleContextAttributeInput extends Omit<RuleAttribute, 'path'> {
10
+ /** Optional — context attributes resolve by KEY from the provided context,
11
+ * so the path is display metadata only. Defaults to `context.<key>`. */
12
+ path?: string;
13
+ }
14
+ export interface RuleContextProvider {
15
+ /** Attributes this provider contributes — registered into the vocabulary. */
16
+ attributes: readonly RuleContextAttributeInput[];
17
+ /** Compute the context values for one evaluation. Pure of side effects. */
18
+ resolve(cart: RuleCartSnapshot): Promise<RuleContext> | RuleContext;
19
+ }
20
+ export declare const ruleContextRegistry: Registry<RuleContextProvider>;
21
+ /**
22
+ * Register a context provider. Its attributes enter the vocabulary
23
+ * immediately (duplicate keys are the I2 hard error registerRuleAttribute
24
+ * throws), so discovery and evaluation can never disagree about what exists.
25
+ */
26
+ export declare function defineRuleContextProvider(id: string, provider: RuleContextProvider, meta?: RegistryMeta): void;
27
+ /**
28
+ * Validate one provider's resolved context against its declaration (I2):
29
+ * unknown keys name the declared set; wrong-typed values name the expected
30
+ * type. Returns only the declared, typed, non-null entries.
31
+ */
32
+ export declare function validateRuleContextResult(id: string, provider: RuleContextProvider, result: RuleContext): RuleContext;
33
+ /**
34
+ * Run every registered provider against the cart and merge the validated
35
+ * results into one context record, keyed by attribute key — the `context`
36
+ * input of computePromotionActions. Key collisions cannot happen here: the
37
+ * vocabulary registry already refused the second registration.
38
+ */
39
+ export declare function buildRuleContext(cart: RuleCartSnapshot): Promise<RuleContext>;
40
+ /** Test seam. Clearing providers does not un-register their vocabulary rows —
41
+ * pair with clearRuleAttributes() in suite teardown. */
42
+ export declare function clearRuleContextProviders(): void;
43
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/rules/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACxC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAEjD,OAAO,KAAK,EAAE,aAAa,EAA0B,MAAM,cAAc,CAAA;AACzE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AA0BpD;;4EAE4E;AAC5E,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;AAEjD,MAAM,WAAW,yBAA0B,SAAQ,IAAI,CAAC,aAAa,EAAE,MAAM,CAAC;IAC5E;6EACyE;IACzE,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,mBAAmB;IAClC,6EAA6E;IAC7E,UAAU,EAAE,SAAS,yBAAyB,EAAE,CAAA;IAChD,2EAA2E;IAC3E,OAAO,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,WAAW,CAAC,GAAG,WAAW,CAAA;CACpE;AAED,eAAO,MAAM,mBAAmB,+BAAmD,CAAA;AAEnF;;;;GAIG;AACH,wBAAgB,yBAAyB,CACvC,EAAE,EAAE,MAAM,EACV,QAAQ,EAAE,mBAAmB,EAC7B,IAAI,GAAE,YAAiB,GACtB,IAAI,CAiBN;AAQD;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,mBAAmB,EAAE,MAAM,EAAE,WAAW,GAAG,WAAW,CAwBrH;AAED;;;;;GAKG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,WAAW,CAAC,CAOnF;AAED;yDACyD;AACzD,wBAAgB,yBAAyB,IAAI,IAAI,CAEhD"}
@@ -0,0 +1,37 @@
1
+ import type { RuleContext } from './context';
2
+ import type { ComputeAction, Promotion, PromotionRule, RuleCartSnapshot } from './rule-types';
3
+ export interface EvaluateOptions {
4
+ /** Extra attribute values, keyed by attribute KEY — the validated output of
5
+ * buildRuleContext (context providers). Wins over snapshot resolution. */
6
+ context?: RuleContext;
7
+ /** ISO timestamp the date-window gates compare against. Default: now. */
8
+ now?: string;
9
+ }
10
+ /** One rule against a flat value list. Values are OR; `ne` is a negative and
11
+ * therefore holds only when NO value equals any rule value. */
12
+ export declare function matchRuleValues(rule: PromotionRule, values: unknown[]): boolean;
13
+ /** ALL rules match (AND). Empty/absent = match. */
14
+ export declare function rulesMatchCart(rules: PromotionRule[] | undefined, cart: RuleCartSnapshot, context?: RuleContext): boolean;
15
+ export type PromotionGateReason = 'inactive' | 'not_started' | 'expired' | 'usage_limit' | 'code_not_entered' | 'rules_not_matched';
16
+ /**
17
+ * Why a promotion does NOT fire against this cart, or null when it does.
18
+ * Shared by the evaluator and the coupon-surface adapter so a rejected code
19
+ * reports the same machine-readable reason everywhere.
20
+ */
21
+ export declare function promotionGateReason(promotion: Promotion, cart: RuleCartSnapshot, options?: EvaluateOptions): PromotionGateReason | null;
22
+ /** Split `total` across weights, in cents, largest-remainder — the parts sum
23
+ * to exactly `total` so a spread discount never loses or invents a cent. */
24
+ export declare function splitProportionally(total: number, weights: number[]): number[];
25
+ /** Deterministic evaluation order: buyget first, specific before generic, id
26
+ * as the final tiebreak. Exported so the SQL mirror's ORDER BY has a named
27
+ * TS counterpart to test against. */
28
+ export declare function orderPromotions(promotions: Promotion[]): Promotion[];
29
+ /**
30
+ * Evaluate promotions against a cart snapshot → the ordered compute-actions
31
+ * the cart applies. Pure and deterministic (inject `now` for date gates).
32
+ */
33
+ export declare function computePromotionActions(cart: RuleCartSnapshot, promotions: Promotion[], options?: EvaluateOptions): ComputeAction[];
34
+ /** Total item+shipping discount an action list carries — the preview number a
35
+ * cart shows. Free items carry no amount (they enter the cart at price 0). */
36
+ export declare function actionsDiscountTotal(actions: ComputeAction[]): number;
37
+ //# sourceMappingURL=evaluator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evaluator.d.ts","sourceRoot":"","sources":["../../src/rules/evaluator.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAK5C,OAAO,KAAK,EAEV,aAAa,EACb,SAAS,EACT,aAAa,EAEb,gBAAgB,EAEjB,MAAM,cAAc,CAAA;AAkCrB,MAAM,WAAW,eAAe;IAC9B;+EAC2E;IAC3E,OAAO,CAAC,EAAE,WAAW,CAAA;IACrB,yEAAyE;IACzE,GAAG,CAAC,EAAE,MAAM,CAAA;CACb;AA4DD;gEACgE;AAChE,wBAAgB,eAAe,CAAC,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAgB/E;AAoBD,mDAAmD;AACnD,wBAAgB,cAAc,CAAC,KAAK,EAAE,aAAa,EAAE,GAAG,SAAS,EAAE,IAAI,EAAE,gBAAgB,EAAE,OAAO,GAAE,WAAgB,GAAG,OAAO,CAE7H;AASD,MAAM,MAAM,mBAAmB,GAC3B,UAAU,GACV,aAAa,GACb,SAAS,GACT,aAAa,GACb,kBAAkB,GAClB,mBAAmB,CAAA;AAEvB;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,SAAS,EACpB,IAAI,EAAE,gBAAgB,EACtB,OAAO,GAAE,eAAoB,GAC5B,mBAAmB,GAAG,IAAI,CAe5B;AAQD;6EAC6E;AAC7E,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAgB9E;AAoJD;;sCAEsC;AACtC,wBAAgB,eAAe,CAAC,UAAU,EAAE,SAAS,EAAE,GAAG,SAAS,EAAE,CAQpE;AAID;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,gBAAgB,EACtB,UAAU,EAAE,SAAS,EAAE,EACvB,OAAO,GAAE,eAAoB,GAC5B,aAAa,EAAE,CAYjB;AAED;+EAC+E;AAC/E,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,aAAa,EAAE,GAAG,MAAM,CAIrE"}
@@ -0,0 +1,13 @@
1
+ export { RULE_OPERATORS, APPLICATION_METHOD_TYPES, APPLICATION_METHOD_TARGET_TYPES, APPLICATION_METHOD_ALLOCATIONS, PROMOTION_TYPES, PROMOTION_STATUSES, cartSubtotal, roundCents, } from './rule-types';
2
+ export type { RuleOperator, RuleValue, PromotionRule, ApplicationMethod, ApplicationMethodType, ApplicationMethodTargetType, ApplicationMethodAllocation, Promotion, PromotionType, PromotionStatus, Campaign, RuleCartItem, RuleCartSnapshot, ComputeAction, AddItemDiscountAction, AddShippingDiscountAction, AddFreeItemAction, } from './rule-types';
3
+ export { RULE_ATTRIBUTE_FIELD_TYPES, CORE_RULE_ATTRIBUTES, ITEM_PATH_PREFIX, ruleAttributeRegistry, registerCoreRuleAttributes, registerRuleAttribute, resolveRuleAttribute, hasRuleAttribute, listRuleAttributeKeys, listRuleAttributes, isItemScopedAttribute, clearRuleAttributes, } from './attributes';
4
+ export type { RuleAttribute, RuleAttributeFieldType, RegisterRuleAttributeOptions } from './attributes';
5
+ export { ruleContextRegistry, defineRuleContextProvider, validateRuleContextResult, buildRuleContext, clearRuleContextProviders, } from './context';
6
+ export type { RuleContext, RuleContextProvider, RuleContextAttributeInput } from './context';
7
+ export { computePromotionActions, promotionGateReason, rulesMatchCart, matchRuleValues, orderPromotions, splitProportionally, actionsDiscountTotal, } from './evaluator';
8
+ export type { EvaluateOptions, PromotionGateReason } from './evaluator';
9
+ export { rankPrices, selectPrice } from './prices';
10
+ export type { PriceCandidate, RankPricesOptions } from './prices';
11
+ export { discountToPromotion, storefrontDiscountToPromotion, previewCouponPercent, } from './adapter';
12
+ export type { StorefrontPercentCode, CouponPreview } from './adapter';
13
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/rules/index.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,cAAc,EACd,wBAAwB,EACxB,+BAA+B,EAC/B,8BAA8B,EAC9B,eAAe,EACf,kBAAkB,EAClB,YAAY,EACZ,UAAU,GACX,MAAM,cAAc,CAAA;AACrB,YAAY,EACV,YAAY,EACZ,SAAS,EACT,aAAa,EACb,iBAAiB,EACjB,qBAAqB,EACrB,2BAA2B,EAC3B,2BAA2B,EAC3B,SAAS,EACT,aAAa,EACb,eAAe,EACf,QAAQ,EACR,YAAY,EACZ,gBAAgB,EAChB,aAAa,EACb,qBAAqB,EACrB,yBAAyB,EACzB,iBAAiB,GAClB,MAAM,cAAc,CAAA;AAErB,OAAO,EACL,0BAA0B,EAC1B,oBAAoB,EACpB,gBAAgB,EAChB,qBAAqB,EACrB,0BAA0B,EAC1B,qBAAqB,EACrB,oBAAoB,EACpB,gBAAgB,EAChB,qBAAqB,EACrB,kBAAkB,EAClB,qBAAqB,EACrB,mBAAmB,GACpB,MAAM,cAAc,CAAA;AACrB,YAAY,EAAE,aAAa,EAAE,sBAAsB,EAAE,4BAA4B,EAAE,MAAM,cAAc,CAAA;AAEvG,OAAO,EACL,mBAAmB,EACnB,yBAAyB,EACzB,yBAAyB,EACzB,gBAAgB,EAChB,yBAAyB,GAC1B,MAAM,WAAW,CAAA;AAClB,YAAY,EAAE,WAAW,EAAE,mBAAmB,EAAE,yBAAyB,EAAE,MAAM,WAAW,CAAA;AAE5F,OAAO,EACL,uBAAuB,EACvB,mBAAmB,EACnB,cAAc,EACd,eAAe,EACf,eAAe,EACf,mBAAmB,EACnB,oBAAoB,GACrB,MAAM,aAAa,CAAA;AACpB,YAAY,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAEvE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AAClD,YAAY,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAA;AAEjE,OAAO,EACL,mBAAmB,EACnB,6BAA6B,EAC7B,oBAAoB,GACrB,MAAM,WAAW,CAAA;AAClB,YAAY,EAAE,qBAAqB,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA"}
@@ -0,0 +1,25 @@
1
+ import type { RuleContext } from './context';
2
+ import type { PromotionRule, RuleCartSnapshot } from './rule-types';
3
+ /** One candidate price for a purchasable. `rules` guard applicability;
4
+ * `priceListId` marks an override list (a price list always outranks a
5
+ * bare price, however many rules the bare price carries). */
6
+ export interface PriceCandidate {
7
+ id: string;
8
+ amount: number;
9
+ priceListId?: string | null;
10
+ rules?: PromotionRule[];
11
+ }
12
+ export interface RankPricesOptions {
13
+ /** Context-provider values, keyed by attribute key (see buildRuleContext). */
14
+ context?: RuleContext;
15
+ }
16
+ /**
17
+ * The applicable candidates, most-precedent first:
18
+ * price_list first, rules_count DESC, amount ASC, id as a stable tiebreak.
19
+ * A candidate whose rules do not ALL match is not in the answer at all —
20
+ * matched_count = rules_count, never partial credit.
21
+ */
22
+ export declare function rankPrices(candidates: PriceCandidate[], cart: RuleCartSnapshot, options?: RankPricesOptions): PriceCandidate[];
23
+ /** The winning price, or null when no candidate's rules all match. */
24
+ export declare function selectPrice(candidates: PriceCandidate[], cart: RuleCartSnapshot, options?: RankPricesOptions): PriceCandidate | null;
25
+ //# sourceMappingURL=prices.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prices.d.ts","sourceRoot":"","sources":["../../src/rules/prices.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAC5C,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAsBnE;;8DAE8D;AAC9D,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,MAAM,CAAA;IACd,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,KAAK,CAAC,EAAE,aAAa,EAAE,CAAA;CACxB;AAED,MAAM,WAAW,iBAAiB;IAChC,8EAA8E;IAC9E,OAAO,CAAC,EAAE,WAAW,CAAA;CACtB;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CACxB,UAAU,EAAE,cAAc,EAAE,EAC5B,IAAI,EAAE,gBAAgB,EACtB,OAAO,GAAE,iBAAsB,GAC9B,cAAc,EAAE,CAYlB;AAED,sEAAsE;AACtE,wBAAgB,WAAW,CACzB,UAAU,EAAE,cAAc,EAAE,EAC5B,IAAI,EAAE,gBAAgB,EACtB,OAAO,GAAE,iBAAsB,GAC9B,cAAc,GAAG,IAAI,CAEvB"}
@@ -0,0 +1,160 @@
1
+ /** The 7 rule operators. This is the closed set — widening it is a model
2
+ * change (TS union + DB CHECK + SQL evaluator), not an insert. */
3
+ export declare const RULE_OPERATORS: readonly ["gte", "lte", "gt", "lt", "eq", "ne", "in"];
4
+ export type RuleOperator = (typeof RULE_OPERATORS)[number];
5
+ /** A rule value is a JSON scalar. The DB stores each in its own
6
+ * plg_shop_rule_values row (values-in-a-child-table, per the model). */
7
+ export type RuleValue = string | number | boolean;
8
+ /**
9
+ * One rule: `attribute` names a row of the rule_attribute VOCABULARY (I9 —
10
+ * never a free-form dotted path; an unknown attribute is an I2 hard error
11
+ * naming the valid set), `operator` is one of the 7, `values` is the child
12
+ * list (a single-element list for scalar operators).
13
+ */
14
+ export interface PromotionRule {
15
+ attribute: string;
16
+ operator: RuleOperator;
17
+ values: RuleValue[];
18
+ }
19
+ export declare const APPLICATION_METHOD_TYPES: readonly ["percentage", "fixed"];
20
+ export type ApplicationMethodType = (typeof APPLICATION_METHOD_TYPES)[number];
21
+ export declare const APPLICATION_METHOD_TARGET_TYPES: readonly ["order", "items", "shipping"];
22
+ export type ApplicationMethodTargetType = (typeof APPLICATION_METHOD_TARGET_TYPES)[number];
23
+ export declare const APPLICATION_METHOD_ALLOCATIONS: readonly ["each", "across", "once"];
24
+ export type ApplicationMethodAllocation = (typeof APPLICATION_METHOD_ALLOCATIONS)[number];
25
+ /**
26
+ * HOW an eligible promotion applies. The six numbers + two rule sets that make
27
+ * buy-N-pay-M pure data:
28
+ *
29
+ * - `type` percentage (value = percentage points) or fixed (value = amount).
30
+ * - `targetType` order (spread across all items) | items | shipping.
31
+ * - `allocation` (items only):
32
+ * each — per unit of each eligible line, `maxQuantity` units per line;
33
+ * across — one amount over the eligible subtotal, split proportionally;
34
+ * once — one unit of the cheapest eligible line, once.
35
+ * - `buyRulesMinQuantity` + `buyRules` — what must be in the cart, and how
36
+ * many, for the promotion to fire (buyget). The promotion applies
37
+ * floor(matched buy quantity / buyRulesMinQuantity) times.
38
+ * - `applyToQuantity` — how many target units each firing discounts.
39
+ * - `targetRules` — which items the discount lands on. A buyget whose target
40
+ * is not in the cart but is pinned to one product id emits addFreeItem.
41
+ */
42
+ export interface ApplicationMethod {
43
+ type: ApplicationMethodType;
44
+ value: number;
45
+ targetType: ApplicationMethodTargetType;
46
+ allocation?: ApplicationMethodAllocation;
47
+ /** Unit cap: per line for `each`; total discounted/free units for buyget. */
48
+ maxQuantity?: number | null;
49
+ /** Buyget: target units discounted per firing. */
50
+ applyToQuantity?: number | null;
51
+ /** Buyget: matched buy quantity required per firing. Null/absent = standard. */
52
+ buyRulesMinQuantity?: number | null;
53
+ /** What gets discounted (the `target` pivot). Absent = every item. */
54
+ targetRules?: PromotionRule[];
55
+ /** What must be bought (the `buy` pivot). Item-scoped attributes only. */
56
+ buyRules?: PromotionRule[];
57
+ }
58
+ export declare const PROMOTION_TYPES: readonly ["standard", "buyget"];
59
+ export type PromotionType = (typeof PROMOTION_TYPES)[number];
60
+ export declare const PROMOTION_STATUSES: readonly ["draft", "active", "inactive"];
61
+ export type PromotionStatus = (typeof PROMOTION_STATUSES)[number];
62
+ /**
63
+ * A promotion: eligibility rules (the `eligibility` pivot) + one application
64
+ * method. `code` promotions fire only when the shopper entered the code
65
+ * (cart.codes); `isAutomatic` promotions fire whenever eligible.
66
+ */
67
+ export interface Promotion {
68
+ id: string;
69
+ /** Coupon code. Null/absent = automatic-only. Matched case-insensitively. */
70
+ code?: string | null;
71
+ isAutomatic?: boolean;
72
+ /** Derivable (buyRulesMinQuantity ⇒ buyget) but stored for the admin UI. */
73
+ type?: PromotionType;
74
+ status?: PromotionStatus;
75
+ campaignId?: string | null;
76
+ /** Does this promotion apply at all? (the `eligibility` pivot). AND across
77
+ * rules; a rule's values are OR. Absent/empty = always eligible. */
78
+ rules?: PromotionRule[];
79
+ applicationMethod: ApplicationMethod;
80
+ startsAt?: string | null;
81
+ endsAt?: string | null;
82
+ usageLimit?: number | null;
83
+ timesUsed?: number;
84
+ }
85
+ /** A campaign groups promotions for reporting/budgets. Parent row only in M6;
86
+ * budget enforcement is a later milestone. */
87
+ export interface Campaign {
88
+ id: string;
89
+ name: string;
90
+ startsAt?: string | null;
91
+ endsAt?: string | null;
92
+ }
93
+ /** One cart line as the engine sees it. Prices are authoritative-catalog
94
+ * prices; the engine never trusts a client-computed total. */
95
+ export interface RuleCartItem {
96
+ /** Line identity actions refer back to. Defaults to productId. */
97
+ id?: string;
98
+ productId: string;
99
+ quantity: number;
100
+ unitPrice: number;
101
+ categoryId?: string | null;
102
+ collectionId?: string | null;
103
+ }
104
+ /**
105
+ * The evaluation input. Serializable on purpose: the SAME snapshot shape is
106
+ * the TS evaluator's input and the SQL function's `p_cart` jsonb, so the
107
+ * preview a shopper sees and the revalidation place_order runs read one
108
+ * contract.
109
+ */
110
+ export interface RuleCartSnapshot {
111
+ items: RuleCartItem[];
112
+ /** Quoted shipping — what a shipping-target promotion discounts. */
113
+ shippingTotal?: number | null;
114
+ /** Shipping region/zone identifier (the shipping.region attribute). */
115
+ region?: string | null;
116
+ customer?: {
117
+ email?: string | null;
118
+ tags?: string[];
119
+ };
120
+ /** Promotion codes the shopper entered (the code attribute; case-insensitive). */
121
+ codes?: string[];
122
+ currency?: string;
123
+ }
124
+ /** Discount one cart line by an absolute amount (already allocation-resolved). */
125
+ export interface AddItemDiscountAction {
126
+ action: 'addItemDiscount';
127
+ promotionId: string;
128
+ code?: string | null;
129
+ itemId: string;
130
+ amount: number;
131
+ }
132
+ /** Discount the shipping total by an absolute amount. */
133
+ export interface AddShippingDiscountAction {
134
+ action: 'addShippingDiscount';
135
+ promotionId: string;
136
+ code?: string | null;
137
+ amount: number;
138
+ }
139
+ /** Add `quantity` free units of a product the buyget promotion grants but the
140
+ * cart does not contain. The cart applies it by adding the line at price 0. */
141
+ export interface AddFreeItemAction {
142
+ action: 'addFreeItem';
143
+ promotionId: string;
144
+ code?: string | null;
145
+ productId: string;
146
+ quantity: number;
147
+ }
148
+ /**
149
+ * The ordered action list computePromotionActions returns. Deterministic:
150
+ * buyget promotions first (they consume target units), then by specificity
151
+ * (total rules count DESC), then id — so replaying the same cart against the
152
+ * same promotions always yields byte-identical actions.
153
+ */
154
+ export type ComputeAction = AddItemDiscountAction | AddShippingDiscountAction | AddFreeItemAction;
155
+ /** Sum of a cart's line totals, cents-rounded — the number `cart.subtotal`
156
+ * rules compare against. */
157
+ export declare function cartSubtotal(cart: RuleCartSnapshot): number;
158
+ /** Cents rounding, the house money convention (commerce.ts round2). */
159
+ export declare function roundCents(value: number): number;
160
+ //# sourceMappingURL=rule-types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rule-types.d.ts","sourceRoot":"","sources":["../../src/rules/rule-types.ts"],"names":[],"mappings":"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"}
package/dist/rules.js ADDED
@@ -0,0 +1,22 @@
1
+ import { rulesMatchCart } from './chunk-3GERSY5F.js';
2
+ export { APPLICATION_METHOD_ALLOCATIONS, APPLICATION_METHOD_TARGET_TYPES, APPLICATION_METHOD_TYPES, CORE_RULE_ATTRIBUTES, ITEM_PATH_PREFIX, PROMOTION_STATUSES, PROMOTION_TYPES, RULE_ATTRIBUTE_FIELD_TYPES, RULE_OPERATORS, actionsDiscountTotal, buildRuleContext, cartSubtotal, clearRuleAttributes, clearRuleContextProviders, computePromotionActions, defineRuleContextProvider, discountToPromotion, hasRuleAttribute, isItemScopedAttribute, listRuleAttributeKeys, listRuleAttributes, matchRuleValues, orderPromotions, previewCouponPercent, promotionGateReason, registerCoreRuleAttributes, registerRuleAttribute, resolveRuleAttribute, roundCents, ruleAttributeRegistry, ruleContextRegistry, rulesMatchCart, splitProportionally, storefrontDiscountToPromotion, validateRuleContextResult } from './chunk-3GERSY5F.js';
3
+
4
+ // src/rules/prices.ts
5
+ function rankPrices(candidates, cart, options = {}) {
6
+ const context = options.context ?? {};
7
+ return candidates.filter((candidate) => rulesMatchCart(candidate.rules, cart, context)).sort((a, b) => {
8
+ const list = Number(b.priceListId != null) - Number(a.priceListId != null);
9
+ if (list !== 0) return list;
10
+ const specificity = (b.rules?.length ?? 0) - (a.rules?.length ?? 0);
11
+ if (specificity !== 0) return specificity;
12
+ if (a.amount !== b.amount) return a.amount - b.amount;
13
+ return a.id.localeCompare(b.id);
14
+ });
15
+ }
16
+ function selectPrice(candidates, cart, options = {}) {
17
+ return rankPrices(candidates, cart, options)[0] ?? null;
18
+ }
19
+
20
+ export { rankPrices, selectPrice };
21
+ //# sourceMappingURL=rules.js.map
22
+ //# sourceMappingURL=rules.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/rules/prices.ts"],"names":[],"mappings":";;;;AA6CO,SAAS,UAAA,CACd,UAAA,EACA,IAAA,EACA,OAAA,GAA6B,EAAC,EACZ;AAClB,EAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,OAAA,IAAW,EAAC;AACpC,EAAA,OAAO,UAAA,CACJ,MAAA,CAAO,CAAC,SAAA,KAAc,eAAe,SAAA,CAAU,KAAA,EAAO,IAAA,EAAM,OAAO,CAAC,CAAA,CACpE,IAAA,CAAK,CAAC,GAAG,CAAA,KAAM;AACd,IAAA,MAAM,IAAA,GAAO,OAAO,CAAA,CAAE,WAAA,IAAe,IAAI,CAAA,GAAI,MAAA,CAAO,CAAA,CAAE,WAAA,IAAe,IAAI,CAAA;AACzE,IAAA,IAAI,IAAA,KAAS,GAAG,OAAO,IAAA;AACvB,IAAA,MAAM,eAAe,CAAA,CAAE,KAAA,EAAO,UAAU,CAAA,KAAM,CAAA,CAAE,OAAO,MAAA,IAAU,CAAA,CAAA;AACjE,IAAA,IAAI,WAAA,KAAgB,GAAG,OAAO,WAAA;AAC9B,IAAA,IAAI,EAAE,MAAA,KAAW,CAAA,CAAE,QAAQ,OAAO,CAAA,CAAE,SAAS,CAAA,CAAE,MAAA;AAC/C,IAAA,OAAO,CAAA,CAAE,EAAA,CAAG,aAAA,CAAc,CAAA,CAAE,EAAE,CAAA;AAAA,EAChC,CAAC,CAAA;AACL;AAGO,SAAS,WAAA,CACd,UAAA,EACA,IAAA,EACA,OAAA,GAA6B,EAAC,EACP;AACvB,EAAA,OAAO,WAAW,UAAA,EAAY,IAAA,EAAM,OAAO,CAAA,CAAE,CAAC,CAAA,IAAK,IAAA;AACrD","file":"rules.js","sourcesContent":["import { rulesMatchCart } from './evaluator'\nimport type { RuleContext } from './context'\nimport type { PromotionRule, RuleCartSnapshot } from './rule-types'\n\n// ---------------------------------------------------------------------------\n// Price precedence by rules_count specificity (spine §3 L2) — Medusa's\n// pricing trick (pricing/src/repositories/pricing.ts:228-295), adopted\n// because it makes precedence DERIVABLE FROM THE DATA ALONE:\n//\n// a price applies iff matched_count = rules_count,\n// ranked price_list first, rules_count DESC, amount ASC.\n//\n// \"Applies iff matched_count = rules_count\" is simply \"ALL of its rules\n// match\" — rulesMatchCart. Because the ranking is a pure function of the\n// candidate rows, an agent adding \"VIP customers in Brazil buying more than\n// 10 units get this price\" never reasons about precedence: more rules = more\n// specific = wins; ties resolve to the cheaper price, which is the promise a\n// shopper was shown somewhere.\n//\n// Same rule model, same vocabulary, same evaluator — this is what \"ONE rule\n// engine\" (I8) buys: prices, promotions and shipping share matching\n// semantics, so a rule means the same thing wherever it appears.\n// ---------------------------------------------------------------------------\n\n/** One candidate price for a purchasable. `rules` guard applicability;\n * `priceListId` marks an override list (a price list always outranks a\n * bare price, however many rules the bare price carries). */\nexport interface PriceCandidate {\n id: string\n amount: number\n priceListId?: string | null\n rules?: PromotionRule[]\n}\n\nexport interface RankPricesOptions {\n /** Context-provider values, keyed by attribute key (see buildRuleContext). */\n context?: RuleContext\n}\n\n/**\n * The applicable candidates, most-precedent first:\n * price_list first, rules_count DESC, amount ASC, id as a stable tiebreak.\n * A candidate whose rules do not ALL match is not in the answer at all —\n * matched_count = rules_count, never partial credit.\n */\nexport function rankPrices(\n candidates: PriceCandidate[],\n cart: RuleCartSnapshot,\n options: RankPricesOptions = {},\n): PriceCandidate[] {\n const context = options.context ?? {}\n return candidates\n .filter((candidate) => rulesMatchCart(candidate.rules, cart, context))\n .sort((a, b) => {\n const list = Number(b.priceListId != null) - Number(a.priceListId != null)\n if (list !== 0) return list\n const specificity = (b.rules?.length ?? 0) - (a.rules?.length ?? 0)\n if (specificity !== 0) return specificity\n if (a.amount !== b.amount) return a.amount - b.amount\n return a.id.localeCompare(b.id)\n })\n}\n\n/** The winning price, or null when no candidate's rules all match. */\nexport function selectPrice(\n candidates: PriceCandidate[],\n cart: RuleCartSnapshot,\n options: RankPricesOptions = {},\n): PriceCandidate | null {\n return rankPrices(candidates, cart, options)[0] ?? null\n}\n"]}
package/dist/runtime.d.ts CHANGED
@@ -1,5 +1,2 @@
1
- import type { ShopProvider } from './provider';
2
- export declare function getShopProvider(): ShopProvider;
3
- export declare function setShopProvider(nextProvider: ShopProvider): void;
4
- export declare function resetShopProvider(): void;
1
+ export * from './lib/runtime';
5
2
  //# sourceMappingURL=runtime.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAM9C,wBAAgB,eAAe,IAAI,YAAY,CAI9C;AAED,wBAAgB,eAAe,CAAC,YAAY,EAAE,YAAY,GAAG,IAAI,CAEhE;AAED,wBAAgB,iBAAiB,IAAI,IAAI,CAGxC"}
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAEA,cAAc,eAAe,CAAA"}
package/dist/runtime.js CHANGED
@@ -1,5 +1,7 @@
1
- export { getShopProvider, resetShopProvider, setShopProvider } from './chunk-IYQHKMLB.js';
2
- import './chunk-SVTCJ6HP.js';
3
- import './chunk-CTKZ6O2J.js';
1
+ export { getShopProvider, resetShopProvider, setShopProvider } from './chunk-2WACO2TG.js';
2
+ import './chunk-U6HV3LVP.js';
3
+ import './chunk-IKNGCRUM.js';
4
+ import './chunk-NWW3WJ7Y.js';
5
+ import './chunk-3GERSY5F.js';
4
6
  //# sourceMappingURL=runtime.js.map
5
7
  //# sourceMappingURL=runtime.js.map
@@ -0,0 +1,43 @@
1
+ import type { ShippingLabel, ShippingLabelOption } from '../types';
2
+ export interface ShippingLabelProvider {
3
+ /** Connector slug — the id `plg_connections.connector_id` carries. */
4
+ id: string;
5
+ /** How the merchant knows them ("Melhor Envio"). Shown in the panel. */
6
+ label: string;
7
+ /** Services and prices for one order. Free, repeatable, spends nothing. */
8
+ quote(orderId: string): Promise<{
9
+ options: ShippingLabelOption[];
10
+ label: ShippingLabel | null;
11
+ }>;
12
+ /** SPENDS the merchant's balance. Idempotent per order by contract. */
13
+ buy(orderId: string, serviceId: number): Promise<ShippingLabel>;
14
+ /** The label PDF, as many times as the merchant needs it. */
15
+ print(orderId: string): Promise<string | null>;
16
+ /** What the carrier says now. */
17
+ track(orderId: string): Promise<ShippingLabel['tracking']>;
18
+ }
19
+ export declare function registerShippingLabelProvider(provider: ShippingLabelProvider): void;
20
+ export declare function listShippingLabelProviders(): ShippingLabelProvider[];
21
+ /** Test seam — the registry is module state, and a test that registers a fake
22
+ * must not leak it into the next one. */
23
+ export declare function resetShippingLabelProviders(): void;
24
+ export interface ResolveShippingLabelOptions {
25
+ /** Connector ids the store has ACTIVE, in the order the panel lists them. */
26
+ connected: readonly string[];
27
+ /**
28
+ * The merchant's explicit choice, when they made one.
29
+ *
30
+ * `''` (empty, not undefined) is a decision too — "I print labels myself" —
31
+ * and it must beat every connected carrier, exactly as the payment provider
32
+ * setting treats "confirmo à mão".
33
+ */
34
+ preferred?: string | null;
35
+ }
36
+ /**
37
+ * Which carrier issues this store's labels — or nobody.
38
+ *
39
+ * Null is a first-class answer and the common one: most stores dispatch by hand,
40
+ * and the panel must show them the manual path without a dead button beside it.
41
+ */
42
+ export declare function resolveShippingLabelProvider(options: ResolveShippingLabelOptions): ShippingLabelProvider | null;
43
+ //# sourceMappingURL=label-provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"label-provider.d.ts","sourceRoot":"","sources":["../../src/shipping/label-provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAA;AAiBlE,MAAM,WAAW,qBAAqB;IACpC,sEAAsE;IACtE,EAAE,EAAE,MAAM,CAAA;IACV,wEAAwE;IACxE,KAAK,EAAE,MAAM,CAAA;IACb,2EAA2E;IAC3E,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,mBAAmB,EAAE,CAAC;QAAC,KAAK,EAAE,aAAa,GAAG,IAAI,CAAA;KAAE,CAAC,CAAA;IAChG,uEAAuE;IACvE,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAAA;IAC/D,6DAA6D;IAC7D,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;IAC9C,iCAAiC;IACjC,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC,CAAA;CAC3D;AAID,wBAAgB,6BAA6B,CAAC,QAAQ,EAAE,qBAAqB,GAAG,IAAI,CAEnF;AAED,wBAAgB,0BAA0B,IAAI,qBAAqB,EAAE,CAEpE;AAED;0CAC0C;AAC1C,wBAAgB,2BAA2B,IAAI,IAAI,CAElD;AAED,MAAM,WAAW,2BAA2B;IAC1C,6EAA6E;IAC7E,SAAS,EAAE,SAAS,MAAM,EAAE,CAAA;IAC5B;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAC1B;AAED;;;;;GAKG;AACH,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,2BAA2B,GACnC,qBAAqB,GAAG,IAAI,CAkB9B"}