@scrawn/core 0.0.2 → 0.0.6

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 (126) hide show
  1. package/README.md +40 -0
  2. package/dist/config.d.ts +17 -2
  3. package/dist/config.d.ts.map +1 -1
  4. package/dist/config.js +9 -2
  5. package/dist/config.js.map +1 -1
  6. package/dist/core/auth/apiKeyAuth.d.ts +4 -13
  7. package/dist/core/auth/apiKeyAuth.d.ts.map +1 -1
  8. package/dist/core/auth/apiKeyAuth.js +12 -17
  9. package/dist/core/auth/apiKeyAuth.js.map +1 -1
  10. package/dist/core/auth/baseAuth.d.ts +14 -36
  11. package/dist/core/auth/baseAuth.d.ts.map +1 -1
  12. package/dist/core/auth/baseAuth.js +0 -6
  13. package/dist/core/auth/baseAuth.js.map +1 -1
  14. package/dist/core/errors/index.d.ts +192 -0
  15. package/dist/core/errors/index.d.ts.map +1 -0
  16. package/dist/core/errors/index.js +280 -0
  17. package/dist/core/errors/index.js.map +1 -0
  18. package/dist/core/grpc/callContext.d.ts +18 -0
  19. package/dist/core/grpc/callContext.d.ts.map +1 -0
  20. package/dist/core/grpc/callContext.js +35 -0
  21. package/dist/core/grpc/callContext.js.map +1 -0
  22. package/dist/core/grpc/client.d.ts +13 -123
  23. package/dist/core/grpc/client.d.ts.map +1 -1
  24. package/dist/core/grpc/client.js +23 -131
  25. package/dist/core/grpc/client.js.map +1 -1
  26. package/dist/core/grpc/index.d.ts +5 -3
  27. package/dist/core/grpc/index.d.ts.map +1 -1
  28. package/dist/core/grpc/index.js +4 -2
  29. package/dist/core/grpc/index.js.map +1 -1
  30. package/dist/core/grpc/requestBuilder.d.ts +12 -113
  31. package/dist/core/grpc/requestBuilder.d.ts.map +1 -1
  32. package/dist/core/grpc/requestBuilder.js +36 -126
  33. package/dist/core/grpc/requestBuilder.js.map +1 -1
  34. package/dist/core/grpc/streamRequestBuilder.d.ts +13 -0
  35. package/dist/core/grpc/streamRequestBuilder.d.ts.map +1 -0
  36. package/dist/core/grpc/streamRequestBuilder.js +60 -0
  37. package/dist/core/grpc/streamRequestBuilder.js.map +1 -0
  38. package/dist/core/grpc/types.d.ts +5 -52
  39. package/dist/core/grpc/types.d.ts.map +1 -1
  40. package/dist/core/grpc/types.js +0 -7
  41. package/dist/core/grpc/types.js.map +1 -1
  42. package/dist/core/pricing/builders.d.ts +157 -0
  43. package/dist/core/pricing/builders.d.ts.map +1 -0
  44. package/dist/core/pricing/builders.js +218 -0
  45. package/dist/core/pricing/builders.js.map +1 -0
  46. package/dist/core/pricing/index.d.ts +30 -0
  47. package/dist/core/pricing/index.d.ts.map +1 -0
  48. package/dist/core/pricing/index.js +32 -0
  49. package/dist/core/pricing/index.js.map +1 -0
  50. package/dist/core/pricing/resolve.d.ts +39 -0
  51. package/dist/core/pricing/resolve.d.ts.map +1 -0
  52. package/dist/core/pricing/resolve.js +50 -0
  53. package/dist/core/pricing/resolve.js.map +1 -0
  54. package/dist/core/pricing/serialize.d.ts +55 -0
  55. package/dist/core/pricing/serialize.d.ts.map +1 -0
  56. package/dist/core/pricing/serialize.js +127 -0
  57. package/dist/core/pricing/serialize.js.map +1 -0
  58. package/dist/core/pricing/types.d.ts +122 -0
  59. package/dist/core/pricing/types.d.ts.map +1 -0
  60. package/dist/core/pricing/types.js +17 -0
  61. package/dist/core/pricing/types.js.map +1 -0
  62. package/dist/core/pricing/validate.d.ts +56 -0
  63. package/dist/core/pricing/validate.d.ts.map +1 -0
  64. package/dist/core/pricing/validate.js +162 -0
  65. package/dist/core/pricing/validate.js.map +1 -0
  66. package/dist/core/scrawn.d.ts +218 -17
  67. package/dist/core/scrawn.d.ts.map +1 -1
  68. package/dist/core/scrawn.js +469 -71
  69. package/dist/core/scrawn.js.map +1 -1
  70. package/dist/core/types/auth.d.ts +1 -1
  71. package/dist/core/types/event.d.ts +182 -18
  72. package/dist/core/types/event.d.ts.map +1 -1
  73. package/dist/core/types/event.js +133 -5
  74. package/dist/core/types/event.js.map +1 -1
  75. package/dist/gen/auth/v1/auth_grpc_pb.d.ts +3 -0
  76. package/dist/gen/auth/v1/auth_grpc_pb.js +45 -0
  77. package/dist/gen/auth/v1/auth_pb.d.ts +63 -57
  78. package/dist/gen/auth/v1/auth_pb.js +471 -86
  79. package/dist/gen/data/v1/data_grpc_pb.d.ts +5 -0
  80. package/dist/gen/data/v1/data_grpc_pb.js +44 -0
  81. package/dist/gen/data/v1/data_pb.d.ts +254 -0
  82. package/dist/gen/data/v1/data_pb.js +1530 -0
  83. package/dist/gen/event/v1/event_grpc_pb.d.ts +3 -0
  84. package/dist/gen/event/v1/event_grpc_pb.js +79 -0
  85. package/dist/gen/event/v1/event_pb.d.ts +273 -100
  86. package/dist/gen/event/v1/event_pb.js +1862 -138
  87. package/dist/gen/package.json +3 -0
  88. package/dist/gen/payment/v1/payment_grpc_pb.d.ts +3 -0
  89. package/dist/gen/payment/v1/payment_grpc_pb.js +45 -0
  90. package/dist/gen/payment/v1/payment_pb.d.ts +43 -35
  91. package/dist/gen/payment/v1/payment_pb.js +321 -59
  92. package/dist/gen/query/v1/query_grpc_pb.d.ts +5 -0
  93. package/dist/gen/query/v1/query_grpc_pb.js +44 -0
  94. package/dist/gen/query/v1/query_pb.d.ts +359 -0
  95. package/dist/gen/query/v1/query_pb.js +2327 -0
  96. package/dist/index.d.ts +19 -10
  97. package/dist/index.d.ts.map +1 -1
  98. package/dist/index.js +20 -10
  99. package/dist/index.js.map +1 -1
  100. package/dist/utils/forkAsyncIterable.d.ts +13 -0
  101. package/dist/utils/forkAsyncIterable.d.ts.map +1 -0
  102. package/dist/utils/forkAsyncIterable.js +78 -0
  103. package/dist/utils/forkAsyncIterable.js.map +1 -0
  104. package/dist/utils/logger.d.ts.map +1 -1
  105. package/dist/utils/logger.js +19 -19
  106. package/dist/utils/logger.js.map +1 -1
  107. package/dist/utils/pathMatcher.js +5 -5
  108. package/package.json +19 -15
  109. package/dist/gen/auth/v1/auth_connect.d.ts +0 -22
  110. package/dist/gen/auth/v1/auth_connect.d.ts.map +0 -1
  111. package/dist/gen/auth/v1/auth_connect.js +0 -26
  112. package/dist/gen/auth/v1/auth_connect.js.map +0 -1
  113. package/dist/gen/auth/v1/auth_pb.d.ts.map +0 -1
  114. package/dist/gen/auth/v1/auth_pb.js.map +0 -1
  115. package/dist/gen/event/v1/event_connect.d.ts +0 -22
  116. package/dist/gen/event/v1/event_connect.d.ts.map +0 -1
  117. package/dist/gen/event/v1/event_connect.js +0 -26
  118. package/dist/gen/event/v1/event_connect.js.map +0 -1
  119. package/dist/gen/event/v1/event_pb.d.ts.map +0 -1
  120. package/dist/gen/event/v1/event_pb.js.map +0 -1
  121. package/dist/gen/payment/v1/payment_connect.d.ts +0 -22
  122. package/dist/gen/payment/v1/payment_connect.d.ts.map +0 -1
  123. package/dist/gen/payment/v1/payment_connect.js +0 -26
  124. package/dist/gen/payment/v1/payment_connect.js.map +0 -1
  125. package/dist/gen/payment/v1/payment_pb.d.ts.map +0 -1
  126. package/dist/gen/payment/v1/payment_pb.js.map +0 -1
@@ -0,0 +1,127 @@
1
+ /**
2
+ * Pricing DSL Serialization
3
+ *
4
+ * This module converts typed pricing expression ASTs into string format
5
+ * that the backend can parse and evaluate.
6
+ *
7
+ * Output format examples:
8
+ * - Amount: 250
9
+ * - Tag: tag(PREMIUM_CALL)
10
+ * - Addition: add(100,tag(FEE),250)
11
+ * - Complex: add(mul(tag(PREMIUM_CALL),3),tag(EXTRA_FEE),250)
12
+ *
13
+ * The format is designed to be:
14
+ * - Unambiguous (parseable by the backend)
15
+ * - Human-readable (for debugging)
16
+ * - Compact (minimal whitespace, no quotes around tag names)
17
+ */
18
+ /**
19
+ * Serialize a pricing expression to a string.
20
+ *
21
+ * @param expr - The expression to serialize
22
+ * @returns A string representation that the backend can parse
23
+ *
24
+ * @example
25
+ * ```typescript
26
+ * const expr = add(mul(tag('PREMIUM'), 3), 100);
27
+ * const str = serializeExpr(expr);
28
+ * // "add(mul(tag(PREMIUM),3),100)"
29
+ * ```
30
+ */
31
+ export function serializeExpr(expr) {
32
+ switch (expr.kind) {
33
+ case "amount":
34
+ return serializeAmount(expr);
35
+ case "tag":
36
+ return serializeTag(expr);
37
+ case "exprRef":
38
+ return `expr(${expr.name})`;
39
+ case "op":
40
+ return serializeOp(expr);
41
+ case "inputTokens":
42
+ throw new Error("Cannot serialize unresolved inputTokens() placeholder. " +
43
+ "Token placeholders must be resolved before serialization. " +
44
+ "This is an SDK bug — please report it.");
45
+ case "outputTokens":
46
+ throw new Error("Cannot serialize unresolved outputTokens() placeholder. " +
47
+ "Token placeholders must be resolved before serialization. " +
48
+ "This is an SDK bug — please report it.");
49
+ }
50
+ }
51
+ /**
52
+ * Serialize an amount expression.
53
+ * Just the integer value.
54
+ */
55
+ function serializeAmount(expr) {
56
+ return expr.value.toString();
57
+ }
58
+ /**
59
+ * Serialize a tag expression.
60
+ * Format: tag(TAG_NAME)
61
+ * Tag names are unquoted (validation ensures valid identifier format).
62
+ */
63
+ function serializeTag(expr) {
64
+ return `tag(${expr.name})`;
65
+ }
66
+ /**
67
+ * Serialize an operation expression.
68
+ * Format: op(arg1,arg2,arg3,...)
69
+ */
70
+ function serializeOp(expr) {
71
+ const opName = expr.op.toLowerCase();
72
+ const args = expr.args.map(serializeExpr).join(",");
73
+ return `${opName}(${args})`;
74
+ }
75
+ /**
76
+ * Pretty-print a pricing expression with indentation.
77
+ * Useful for debugging and logging.
78
+ *
79
+ * @param expr - The expression to format
80
+ * @param indent - Number of spaces for indentation (default 2)
81
+ * @returns A formatted, multi-line string representation
82
+ *
83
+ * @example
84
+ * ```typescript
85
+ * const expr = add(mul(tag('PREMIUM'), 3), 100);
86
+ * console.log(prettyPrintExpr(expr));
87
+ * // add(
88
+ * // mul(
89
+ * // tag(PREMIUM),
90
+ * // 3
91
+ * // ),
92
+ * // 100
93
+ * // )
94
+ * ```
95
+ */
96
+ export function prettyPrintExpr(expr, indent = 2) {
97
+ return prettyPrintInternal(expr, 0, indent);
98
+ }
99
+ function prettyPrintInternal(expr, level, indent) {
100
+ const pad = " ".repeat(level * indent);
101
+ switch (expr.kind) {
102
+ case "amount":
103
+ return expr.value.toString();
104
+ case "tag":
105
+ return `tag(${expr.name})`;
106
+ case "exprRef":
107
+ return `expr(${expr.name})`;
108
+ case "inputTokens":
109
+ return "inputTokens()";
110
+ case "outputTokens":
111
+ return "outputTokens()";
112
+ case "op": {
113
+ const opName = expr.op.toLowerCase();
114
+ if (expr.args.length === 0) {
115
+ return `${opName}()`;
116
+ }
117
+ const args = expr.args
118
+ .map((arg) => {
119
+ const inner = prettyPrintInternal(arg, level + 1, indent);
120
+ return " ".repeat((level + 1) * indent) + inner;
121
+ })
122
+ .join(",\n");
123
+ return `${opName}(\n${args}\n${pad})`;
124
+ }
125
+ }
126
+ }
127
+ //# sourceMappingURL=serialize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serialize.js","sourceRoot":"","sources":["../../../src/core/pricing/serialize.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,122 @@
1
+ /**
2
+ * Pricing DSL Types
3
+ *
4
+ * This module defines the type-safe AST for pricing expressions.
5
+ * The SDK builds typed expressions using these types, then serializes
6
+ * them to strings for the backend to parse and evaluate.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * import { add, mul, tag } from '@scrawn/core';
11
+ *
12
+ * // Build a pricing expression: (PREMIUM_CALL * 3) + EXTRA_FEE + 250 cents
13
+ * const expr = add(mul(tag('PREMIUM_CALL'), 3), tag('EXTRA_FEE'), 250);
14
+ * ```
15
+ */
16
+ /**
17
+ * Supported arithmetic operations for pricing expressions.
18
+ */
19
+ export type OpType = "ADD" | "SUB" | "MUL" | "DIV";
20
+ /**
21
+ * Intellisense hint type for tag names.
22
+ * Tag names must be ALL CAPS with underscores only (e.g., PREMIUM_CALL, FEE, INPUT_RATE).
23
+ * No lowercase, digits, or hyphens allowed.
24
+ *
25
+ * This is a branded type that provides IDE hints while remaining compatible with `string`.
26
+ */
27
+ export type TagName = Uppercase<string> & {
28
+ readonly __brand?: "TagName";
29
+ };
30
+ /**
31
+ * A literal amount in cents (must be an integer).
32
+ */
33
+ export interface AmountExpr {
34
+ readonly kind: "amount";
35
+ readonly value: number;
36
+ }
37
+ /**
38
+ * A reference to a named price tag (resolved by the backend).
39
+ * Tag names must be ALL CAPS with underscores only (e.g., PREMIUM_CALL, FEE).
40
+ *
41
+ * @typeParam TTag - The specific tag name literal (defaults to `string` for untyped usage)
42
+ */
43
+ export interface TagExpr<TTag extends string = string> {
44
+ readonly kind: "tag";
45
+ readonly name: TTag;
46
+ }
47
+ /**
48
+ * An arithmetic operation combining multiple expressions.
49
+ *
50
+ * @typeParam TTag - The tag name type flowing through the expression tree
51
+ */
52
+ export interface OpExpr<TTag extends string = string> {
53
+ readonly kind: "op";
54
+ readonly op: OpType;
55
+ readonly args: readonly PriceExpr<TTag>[];
56
+ }
57
+ /**
58
+ * A placeholder for the inputTokens value from an AI token usage payload.
59
+ * Only valid in expressions used with aiTokenStreamConsumer.
60
+ * Resolved SDK-side to an AmountExpr before serialization.
61
+ */
62
+ export interface InputTokensExpr {
63
+ readonly kind: "inputTokens";
64
+ }
65
+ /**
66
+ * A placeholder for the outputTokens value from an AI token usage payload.
67
+ * Only valid in expressions used with aiTokenStreamConsumer.
68
+ * Resolved SDK-side to an AmountExpr before serialization.
69
+ */
70
+ export interface OutputTokensExpr {
71
+ readonly kind: "outputTokens";
72
+ }
73
+ /**
74
+ * A reference to a persisted expression stored in the Scrawn backend.
75
+ * Like tags, persisted expressions have a name and resolve to a value
76
+ * when evaluated by the backend.
77
+ *
78
+ * @example
79
+ * ```typescript
80
+ * const expr = biller.expr("MY_EXPR"); // type-safe reference
81
+ * ```
82
+ */
83
+ export interface ExprRef {
84
+ readonly kind: "exprRef";
85
+ readonly name: string;
86
+ }
87
+ /**
88
+ * A wrapped pricing expression — the only type accepted by `debitExpr` fields.
89
+ *
90
+ * Created exclusively via `biller.expr()`. This wrapper ensures all expressions
91
+ * flow through a consistent entry point that provides type-safety for both
92
+ * inline expressions and persisted expression references.
93
+ *
94
+ * @typeParam TTag - The tag name type flowing through the expression tree
95
+ *
96
+ * @example
97
+ * ```typescript
98
+ * // inline expression
99
+ * const expr = biller.expr(mul(biller.tag("PREMIUM_CALL"), 3));
100
+ *
101
+ * // persisted expression reference
102
+ * const expr = biller.expr("MY_EXPR");
103
+ * ```
104
+ */
105
+ export interface ScrawnExpr<TTag extends string = string> {
106
+ readonly _expr: PriceExpr<TTag> | ExprRef;
107
+ }
108
+ /**
109
+ * A pricing expression - can be a literal amount, a tag reference, an operation,
110
+ * a token placeholder (inputTokens/outputTokens), or a persisted expression reference.
111
+ *
112
+ * @typeParam TTag - The tag name type flowing through the expression tree
113
+ */
114
+ export type PriceExpr<TTag extends string = string> = AmountExpr | TagExpr<TTag> | OpExpr<TTag> | InputTokensExpr | OutputTokensExpr | ExprRef;
115
+ /**
116
+ * Input type for DSL builder functions.
117
+ * Accepts either a PriceExpr or a raw number (interpreted as cents).
118
+ *
119
+ * @typeParam TTag - The tag name type flowing through the expression tree
120
+ */
121
+ export type ExprInput<TTag extends string = string> = PriceExpr<TTag> | ScrawnExpr<TTag> | number;
122
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/core/pricing/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH;;GAEG;AACH,MAAM,MAAM,MAAM,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC;AAEnD;;;;;;GAMG;AACH,MAAM,MAAM,OAAO,GAAG,SAAS,CAAC,MAAM,CAAC,GAAG;IAAE,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,CAAA;CAAE,CAAC;AAE3E;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED;;;;;GAKG;AACH,MAAM,WAAW,OAAO,CAAC,IAAI,SAAS,MAAM,GAAG,MAAM;IACnD,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IACrB,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;CACrB;AAED;;;;GAIG;AACH,MAAM,WAAW,MAAM,CAAC,IAAI,SAAS,MAAM,GAAG,MAAM;IAClD,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,SAAS,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;CAC3C;AAED;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;CAC9B;AAED;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;CAC/B;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,UAAU,CAAC,IAAI,SAAS,MAAM,GAAG,MAAM;IACtD,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC;CAC3C;AAED;;;;;GAKG;AACH,MAAM,MAAM,SAAS,CAAC,IAAI,SAAS,MAAM,GAAG,MAAM,IAC9C,UAAU,GACV,OAAO,CAAC,IAAI,CAAC,GACb,MAAM,CAAC,IAAI,CAAC,GACZ,eAAe,GACf,gBAAgB,GAChB,OAAO,CAAC;AAEZ;;;;;GAKG;AACH,MAAM,MAAM,SAAS,CAAC,IAAI,SAAS,MAAM,GAAG,MAAM,IAAI,SAAS,CAAC,IAAI,CAAC,GAAG,UAAU,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Pricing DSL Types
3
+ *
4
+ * This module defines the type-safe AST for pricing expressions.
5
+ * The SDK builds typed expressions using these types, then serializes
6
+ * them to strings for the backend to parse and evaluate.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * import { add, mul, tag } from '@scrawn/core';
11
+ *
12
+ * // Build a pricing expression: (PREMIUM_CALL * 3) + EXTRA_FEE + 250 cents
13
+ * const expr = add(mul(tag('PREMIUM_CALL'), 3), tag('EXTRA_FEE'), 250);
14
+ * ```
15
+ */
16
+ export {};
17
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/core/pricing/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Pricing DSL Validation
3
+ *
4
+ * This module provides light SDK-side validation for pricing expressions.
5
+ * The backend performs full validation; the SDK only catches obvious errors
6
+ * early to provide better developer experience.
7
+ *
8
+ * SDK validates:
9
+ * - Division by literal zero
10
+ * - Non-integer cents (amounts must be integers)
11
+ * - Non-finite numbers (NaN, Infinity)
12
+ * - Empty operation arguments (ops need at least 2 args)
13
+ * - Empty/whitespace tag names
14
+ * - Tag name format (must be ALL_CAPS with underscores only)
15
+ *
16
+ * SDK does NOT validate:
17
+ * - Tag existence (backend resolves tags)
18
+ * - Division by zero when divisor is a tag (backend handles)
19
+ * - Overflow (backend handles)
20
+ * - Negative results (backend handles)
21
+ */
22
+ import type { PriceExpr } from "./types.js";
23
+ /**
24
+ * Error thrown when a pricing expression fails validation.
25
+ */
26
+ export declare class PricingExpressionError extends Error {
27
+ constructor(message: string);
28
+ }
29
+ /**
30
+ * Validate a pricing expression.
31
+ * Throws PricingExpressionError if validation fails.
32
+ *
33
+ * @param expr - The expression to validate
34
+ * @throws PricingExpressionError if validation fails
35
+ */
36
+ export declare function validateExpr(expr: PriceExpr<string>): void;
37
+ /**
38
+ * Check if an expression is valid without throwing.
39
+ * Returns true if valid, false otherwise.
40
+ *
41
+ * @param expr - The expression to check
42
+ * @returns true if the expression is valid
43
+ */
44
+ export declare function isValidExpr(expr: PriceExpr<string>): boolean;
45
+ /**
46
+ * Check if an expression tree contains any token placeholder nodes
47
+ * (inputTokens or outputTokens).
48
+ *
49
+ * Used to reject token placeholders in contexts where they are not valid
50
+ * (e.g., SDK call event payloads).
51
+ *
52
+ * @param expr - The expression to check
53
+ * @returns true if the expression contains any token placeholders
54
+ */
55
+ export declare function containsTokenExpr(expr: PriceExpr<string>): boolean;
56
+ //# sourceMappingURL=validate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../../src/core/pricing/validate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAU,MAAM,YAAY,CAAC;AAEpD;;GAEG;AACH,qBAAa,sBAAuB,SAAQ,KAAK;gBACnC,OAAO,EAAE,MAAM;CAI5B;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,SAAS,CAAC,MAAM,CAAC,GAAG,IAAI,CAqB1D;AAqFD;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,SAAS,CAAC,MAAM,CAAC,GAAG,OAAO,CAO5D;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,SAAS,CAAC,MAAM,CAAC,GAAG,OAAO,CAYlE"}
@@ -0,0 +1,162 @@
1
+ /**
2
+ * Pricing DSL Validation
3
+ *
4
+ * This module provides light SDK-side validation for pricing expressions.
5
+ * The backend performs full validation; the SDK only catches obvious errors
6
+ * early to provide better developer experience.
7
+ *
8
+ * SDK validates:
9
+ * - Division by literal zero
10
+ * - Non-integer cents (amounts must be integers)
11
+ * - Non-finite numbers (NaN, Infinity)
12
+ * - Empty operation arguments (ops need at least 2 args)
13
+ * - Empty/whitespace tag names
14
+ * - Tag name format (must be ALL_CAPS with underscores only)
15
+ *
16
+ * SDK does NOT validate:
17
+ * - Tag existence (backend resolves tags)
18
+ * - Division by zero when divisor is a tag (backend handles)
19
+ * - Overflow (backend handles)
20
+ * - Negative results (backend handles)
21
+ */
22
+ /**
23
+ * Error thrown when a pricing expression fails validation.
24
+ */
25
+ export class PricingExpressionError extends Error {
26
+ constructor(message) {
27
+ super(message);
28
+ this.name = "PricingExpressionError";
29
+ }
30
+ }
31
+ /**
32
+ * Validate a pricing expression.
33
+ * Throws PricingExpressionError if validation fails.
34
+ *
35
+ * @param expr - The expression to validate
36
+ * @throws PricingExpressionError if validation fails
37
+ */
38
+ export function validateExpr(expr) {
39
+ switch (expr.kind) {
40
+ case "amount":
41
+ validateAmount(expr.value);
42
+ break;
43
+ case "tag":
44
+ validateTagName(expr.name);
45
+ break;
46
+ case "op":
47
+ validateOp(expr);
48
+ break;
49
+ case "exprRef":
50
+ validateTagName(expr.name); // same ALL_CAPS format as tags
51
+ break;
52
+ case "inputTokens":
53
+ case "outputTokens":
54
+ // Token placeholders are valid AST nodes — no validation needed.
55
+ // Context-level validation (e.g., rejecting them in SDK call payloads)
56
+ // is handled in event.ts, not here.
57
+ break;
58
+ }
59
+ }
60
+ /**
61
+ * Validate an amount value.
62
+ * Must be a finite integer.
63
+ */
64
+ function validateAmount(value) {
65
+ if (!Number.isFinite(value)) {
66
+ throw new PricingExpressionError(`Amount must be a finite number, got: ${value}`);
67
+ }
68
+ if (!Number.isInteger(value)) {
69
+ throw new PricingExpressionError(`Amount must be an integer (cents), got: ${value}. ` +
70
+ `Hint: Use cents instead of dollars (e.g., 250 instead of 2.50)`);
71
+ }
72
+ }
73
+ /**
74
+ * Validate a tag name.
75
+ * Must be ALL CAPS with underscores only (e.g., PREMIUM_CALL, FEE, INPUT_RATE).
76
+ * No lowercase, digits, or hyphens allowed.
77
+ */
78
+ function validateTagName(name) {
79
+ if (typeof name !== "string") {
80
+ throw new PricingExpressionError(`Tag name must be a string, got: ${typeof name}`);
81
+ }
82
+ if (name.length === 0) {
83
+ throw new PricingExpressionError("Tag name cannot be empty");
84
+ }
85
+ if (name.trim() !== name) {
86
+ throw new PricingExpressionError(`Tag name cannot have leading or trailing whitespace: "${name}"`);
87
+ }
88
+ if (name.trim().length === 0) {
89
+ throw new PricingExpressionError("Tag name cannot be only whitespace");
90
+ }
91
+ // Validate tag name format: ALL CAPS with underscores only
92
+ if (!/^[A-Z_]+$/.test(name)) {
93
+ throw new PricingExpressionError(`Tag name must be ALL CAPS with underscores only (e.g., PREMIUM_CALL, FEE). ` +
94
+ `No lowercase, digits, or hyphens allowed. Got: "${name}"`);
95
+ }
96
+ }
97
+ /**
98
+ * Validate an operation expression.
99
+ * Must have at least 2 arguments.
100
+ * For division, checks for literal zero divisors.
101
+ */
102
+ function validateOp(expr) {
103
+ const { op, args } = expr;
104
+ // Must have at least 2 arguments
105
+ if (args.length < 2) {
106
+ throw new PricingExpressionError(`Operation ${op.toLowerCase()} requires at least 2 arguments, got: ${args.length}`);
107
+ }
108
+ // Recursively validate all arguments
109
+ for (const arg of args) {
110
+ validateExpr(arg);
111
+ }
112
+ // Check for division by literal zero
113
+ if (op === "DIV") {
114
+ // Check all divisors (all args after the first)
115
+ for (let i = 1; i < args.length; i++) {
116
+ const arg = args[i];
117
+ if (arg.kind === "amount" && arg.value === 0) {
118
+ throw new PricingExpressionError(`Division by zero: divisor at position ${i + 1} is 0`);
119
+ }
120
+ }
121
+ }
122
+ }
123
+ /**
124
+ * Check if an expression is valid without throwing.
125
+ * Returns true if valid, false otherwise.
126
+ *
127
+ * @param expr - The expression to check
128
+ * @returns true if the expression is valid
129
+ */
130
+ export function isValidExpr(expr) {
131
+ try {
132
+ validateExpr(expr);
133
+ return true;
134
+ }
135
+ catch {
136
+ return false;
137
+ }
138
+ }
139
+ /**
140
+ * Check if an expression tree contains any token placeholder nodes
141
+ * (inputTokens or outputTokens).
142
+ *
143
+ * Used to reject token placeholders in contexts where they are not valid
144
+ * (e.g., SDK call event payloads).
145
+ *
146
+ * @param expr - The expression to check
147
+ * @returns true if the expression contains any token placeholders
148
+ */
149
+ export function containsTokenExpr(expr) {
150
+ switch (expr.kind) {
151
+ case "inputTokens":
152
+ case "outputTokens":
153
+ return true;
154
+ case "op":
155
+ return expr.args.some(containsTokenExpr);
156
+ case "amount":
157
+ case "tag":
158
+ case "exprRef":
159
+ return false;
160
+ }
161
+ }
162
+ //# sourceMappingURL=validate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../../src/core/pricing/validate.ts"],"names":[],"mappings":"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"}