@opencard-dev/core 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/db.d.ts +145 -0
- package/dist/db.d.ts.map +1 -0
- package/dist/db.js +373 -0
- package/dist/db.js.map +1 -0
- package/dist/errors.d.ts +72 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +124 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +34 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +67 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +53 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +109 -0
- package/dist/logger.js.map +1 -0
- package/dist/rules-engine.d.ts +159 -0
- package/dist/rules-engine.d.ts.map +1 -0
- package/dist/rules-engine.js +375 -0
- package/dist/rules-engine.js.map +1 -0
- package/dist/rules-store.d.ts +187 -0
- package/dist/rules-store.d.ts.map +1 -0
- package/dist/rules-store.js +291 -0
- package/dist/rules-store.js.map +1 -0
- package/dist/rules-validation.d.ts +54 -0
- package/dist/rules-validation.d.ts.map +1 -0
- package/dist/rules-validation.js +110 -0
- package/dist/rules-validation.js.map +1 -0
- package/dist/stripe-client.d.ts +154 -0
- package/dist/stripe-client.d.ts.map +1 -0
- package/dist/stripe-client.js +444 -0
- package/dist/stripe-client.js.map +1 -0
- package/dist/test-utils.d.ts +55 -0
- package/dist/test-utils.d.ts.map +1 -0
- package/dist/test-utils.js +91 -0
- package/dist/test-utils.js.map +1 -0
- package/dist/tracker.d.ts +130 -0
- package/dist/tracker.d.ts.map +1 -0
- package/dist/tracker.js +196 -0
- package/dist/tracker.js.map +1 -0
- package/dist/transaction-reconciler.d.ts +30 -0
- package/dist/transaction-reconciler.d.ts.map +1 -0
- package/dist/transaction-reconciler.js +131 -0
- package/dist/transaction-reconciler.js.map +1 -0
- package/dist/types.d.ts +194 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +7 -0
- package/dist/types.js.map +1 -0
- package/dist/webhooks.d.ts +121 -0
- package/dist/webhooks.d.ts.map +1 -0
- package/dist/webhooks.js +307 -0
- package/dist/webhooks.js.map +1 -0
- package/package.json +46 -0
package/dist/errors.js
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* OpenCard Error Classes
|
|
4
|
+
* ======================
|
|
5
|
+
* Custom error types for OpenCard, designed to wrap Stripe errors while
|
|
6
|
+
* preserving the original error code, message, and type.
|
|
7
|
+
*
|
|
8
|
+
* This allows callers to recover from specific errors (e.g., retry on
|
|
9
|
+
* rate limits, handle authorization failures differently) rather than
|
|
10
|
+
* treating all errors as opaque strings.
|
|
11
|
+
*/
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.RuleError = exports.InvalidParameterError = exports.RateLimitError = exports.StripeAuthenticationError = exports.OpenCardError = void 0;
|
|
14
|
+
exports.wrapStripeError = wrapStripeError;
|
|
15
|
+
/**
|
|
16
|
+
* Base class for all OpenCard errors.
|
|
17
|
+
* Extends Error and preserves the Stripe error context.
|
|
18
|
+
*/
|
|
19
|
+
class OpenCardError extends Error {
|
|
20
|
+
/** Original error if this is wrapping a thrown error */
|
|
21
|
+
cause;
|
|
22
|
+
/** Context about what operation failed (stripe-client, rules-engine, etc.) */
|
|
23
|
+
component;
|
|
24
|
+
/** Stripe error code if available (e.g., 'rate_limit_error', 'authentication_error') */
|
|
25
|
+
stripeCode;
|
|
26
|
+
/** Stripe error type if available (e.g., 'StripeInvalidRequestError') */
|
|
27
|
+
stripeType;
|
|
28
|
+
/** Additional context (cardId, ruleId, etc.) */
|
|
29
|
+
context;
|
|
30
|
+
constructor(message, component, context = {}) {
|
|
31
|
+
super(message);
|
|
32
|
+
this.name = 'OpenCardError';
|
|
33
|
+
this.component = component;
|
|
34
|
+
this.context = context;
|
|
35
|
+
// Maintain proper prototype chain for instanceof checks
|
|
36
|
+
Object.setPrototypeOf(this, OpenCardError.prototype);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
exports.OpenCardError = OpenCardError;
|
|
40
|
+
/**
|
|
41
|
+
* Wraps a Stripe error, preserving its type and code.
|
|
42
|
+
* Useful for error recovery based on the specific Stripe error.
|
|
43
|
+
*
|
|
44
|
+
* @param error - The original error (likely from a Stripe SDK call)
|
|
45
|
+
* @param message - User-friendly message describing what we were doing
|
|
46
|
+
* @param component - Component name (e.g., 'stripe-client')
|
|
47
|
+
* @param context - Additional context (cardId, etc.)
|
|
48
|
+
* @returns OpenCardError with Stripe error info preserved
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* try {
|
|
52
|
+
* await stripe.issuing.cards.create({ ... });
|
|
53
|
+
* } catch (err) {
|
|
54
|
+
* throw wrapStripeError(err, 'Failed to create card', 'stripe-client', { cardholderId });
|
|
55
|
+
* }
|
|
56
|
+
*/
|
|
57
|
+
function wrapStripeError(error, message, component, context = {}) {
|
|
58
|
+
const err = new OpenCardError(message, component, context);
|
|
59
|
+
if (error instanceof Error) {
|
|
60
|
+
err.cause = error;
|
|
61
|
+
err.message = `${message}: ${error.message}`;
|
|
62
|
+
// Extract Stripe-specific error info if available
|
|
63
|
+
const stripeErr = error;
|
|
64
|
+
if (stripeErr.code) {
|
|
65
|
+
err.stripeCode = stripeErr.code;
|
|
66
|
+
}
|
|
67
|
+
if (stripeErr.type) {
|
|
68
|
+
err.stripeType = stripeErr.type;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
err.message = `${message}: ${String(error)}`;
|
|
73
|
+
}
|
|
74
|
+
Object.setPrototypeOf(err, OpenCardError.prototype);
|
|
75
|
+
return err;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Specific error: Stripe authentication failed (invalid key, revoked key, etc.)
|
|
79
|
+
*/
|
|
80
|
+
class StripeAuthenticationError extends OpenCardError {
|
|
81
|
+
constructor(message, context = {}) {
|
|
82
|
+
super(message, 'stripe-client', context);
|
|
83
|
+
this.name = 'StripeAuthenticationError';
|
|
84
|
+
Object.setPrototypeOf(this, StripeAuthenticationError.prototype);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
exports.StripeAuthenticationError = StripeAuthenticationError;
|
|
88
|
+
/**
|
|
89
|
+
* Specific error: Rate limit exceeded — client should retry with backoff.
|
|
90
|
+
*/
|
|
91
|
+
class RateLimitError extends OpenCardError {
|
|
92
|
+
/** Seconds to wait before retrying (from Stripe's Retry-After header) */
|
|
93
|
+
retryAfter;
|
|
94
|
+
constructor(message, component, retryAfter, context = {}) {
|
|
95
|
+
super(message, component, context);
|
|
96
|
+
this.name = 'RateLimitError';
|
|
97
|
+
this.retryAfter = retryAfter;
|
|
98
|
+
Object.setPrototypeOf(this, RateLimitError.prototype);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
exports.RateLimitError = RateLimitError;
|
|
102
|
+
/**
|
|
103
|
+
* Specific error: Invalid parameters (e.g., missing required field, bad enum value)
|
|
104
|
+
*/
|
|
105
|
+
class InvalidParameterError extends OpenCardError {
|
|
106
|
+
constructor(message, context = {}) {
|
|
107
|
+
super(message, 'stripe-client', context);
|
|
108
|
+
this.name = 'InvalidParameterError';
|
|
109
|
+
Object.setPrototypeOf(this, InvalidParameterError.prototype);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
exports.InvalidParameterError = InvalidParameterError;
|
|
113
|
+
/**
|
|
114
|
+
* Specific error: Rule not found or invalid in the rules store.
|
|
115
|
+
*/
|
|
116
|
+
class RuleError extends OpenCardError {
|
|
117
|
+
constructor(message, context = {}) {
|
|
118
|
+
super(message, 'rules-store', context);
|
|
119
|
+
this.name = 'RuleError';
|
|
120
|
+
Object.setPrototypeOf(this, RuleError.prototype);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
exports.RuleError = RuleError;
|
|
124
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @opencard/core — Public API
|
|
3
|
+
* ==========================
|
|
4
|
+
* Everything a consumer of this package needs is re-exported from here.
|
|
5
|
+
* Import paths never need to go deeper than "@opencard/core".
|
|
6
|
+
*
|
|
7
|
+
* Organized into logical sections:
|
|
8
|
+
* - Types: TypeScript interfaces and type aliases
|
|
9
|
+
* - Client: The StripeClient wrapper for Stripe Issuing
|
|
10
|
+
* - Rules: Rule builder, templates, and evaluation
|
|
11
|
+
* - Tracker: In-memory spend tracking
|
|
12
|
+
* - Webhooks: Stripe event handlers
|
|
13
|
+
*/
|
|
14
|
+
export type { OpenCardConfig, Cardholder, BillingDetails, CardCreateOptions, Card, SpendRule, SpendRuleTemplate, Transaction, Authorization, CardBalance, TransactionQueryOptions, SpendingLimits, StripeOperationConfig, } from './types';
|
|
15
|
+
export { StripeClient } from './stripe-client';
|
|
16
|
+
export { SpendRules, evaluateRule, evaluateAuthorization } from './rules-engine';
|
|
17
|
+
export type { AuthorizationDecision, SpendContext } from './rules-engine';
|
|
18
|
+
export { TransactionTracker, tracker } from './tracker';
|
|
19
|
+
export type { CardSpend } from './tracker';
|
|
20
|
+
export { RulesStore, rulesStore } from './rules-store';
|
|
21
|
+
export { validateRule } from './rules-validation';
|
|
22
|
+
export type { ValidationResult } from './rules-validation';
|
|
23
|
+
export { mockAuthorization } from './test-utils';
|
|
24
|
+
export type { MockAuthorizationParams } from './test-utils';
|
|
25
|
+
export { handleAuthorizationRequest, handleAuthorizationCreated, handleTransactionCreated, handleCardUpdated, setReconciler, getReconciler, getRulesForCard, } from './webhooks';
|
|
26
|
+
export type { AuthorizationResult } from './webhooks';
|
|
27
|
+
export { OpenCardDatabase, initDatabase } from './db';
|
|
28
|
+
export type { StoredTransaction, StoredAuthorization, RuleVersion, StoredRule, StoredCard, StoredCardholder, ApprovalRequest, } from './db';
|
|
29
|
+
export { TransactionReconciler } from './transaction-reconciler';
|
|
30
|
+
export type { ReconciliationResult } from './transaction-reconciler';
|
|
31
|
+
export { getLogger, configureLogger } from './logger';
|
|
32
|
+
export type { LogLevel, LogEntry } from './logger';
|
|
33
|
+
export { OpenCardError, wrapStripeError, StripeAuthenticationError, RateLimitError, InvalidParameterError, RuleError, } from './errors';
|
|
34
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH,YAAY,EACV,cAAc,EACd,UAAU,EACV,cAAc,EACd,iBAAiB,EACjB,IAAI,EACJ,SAAS,EACT,iBAAiB,EACjB,WAAW,EACX,aAAa,EACb,WAAW,EACX,uBAAuB,EACvB,cAAc,EACd,qBAAqB,GACtB,MAAM,SAAS,CAAC;AAIjB,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAI/C,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AACjF,YAAY,EAAE,qBAAqB,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAI1E,OAAO,EAAE,kBAAkB,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACxD,YAAY,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAI3C,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAIvD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,YAAY,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAI3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,YAAY,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AAI5D,OAAO,EACL,0BAA0B,EAC1B,0BAA0B,EAC1B,wBAAwB,EACxB,iBAAiB,EACjB,aAAa,EACb,aAAa,EACb,eAAe,GAChB,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAItD,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,MAAM,CAAC;AACtD,YAAY,EACV,iBAAiB,EACjB,mBAAmB,EACnB,WAAW,EACX,UAAU,EACV,UAAU,EACV,gBAAgB,EAChB,eAAe,GAChB,MAAM,MAAM,CAAC;AAId,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AACjE,YAAY,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAIrE,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AACtD,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAInD,OAAO,EACL,aAAa,EACb,eAAe,EACf,yBAAyB,EACzB,cAAc,EACd,qBAAqB,EACrB,SAAS,GACV,MAAM,UAAU,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @opencard/core — Public API
|
|
4
|
+
* ==========================
|
|
5
|
+
* Everything a consumer of this package needs is re-exported from here.
|
|
6
|
+
* Import paths never need to go deeper than "@opencard/core".
|
|
7
|
+
*
|
|
8
|
+
* Organized into logical sections:
|
|
9
|
+
* - Types: TypeScript interfaces and type aliases
|
|
10
|
+
* - Client: The StripeClient wrapper for Stripe Issuing
|
|
11
|
+
* - Rules: Rule builder, templates, and evaluation
|
|
12
|
+
* - Tracker: In-memory spend tracking
|
|
13
|
+
* - Webhooks: Stripe event handlers
|
|
14
|
+
*/
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.RuleError = exports.InvalidParameterError = exports.RateLimitError = exports.StripeAuthenticationError = exports.wrapStripeError = exports.OpenCardError = exports.configureLogger = exports.getLogger = exports.TransactionReconciler = exports.initDatabase = exports.OpenCardDatabase = exports.getRulesForCard = exports.getReconciler = exports.setReconciler = exports.handleCardUpdated = exports.handleTransactionCreated = exports.handleAuthorizationCreated = exports.handleAuthorizationRequest = exports.mockAuthorization = exports.validateRule = exports.rulesStore = exports.RulesStore = exports.tracker = exports.TransactionTracker = exports.evaluateAuthorization = exports.evaluateRule = exports.SpendRules = exports.StripeClient = void 0;
|
|
17
|
+
// ─── Stripe Client ────────────────────────────────────────────────────────────
|
|
18
|
+
var stripe_client_1 = require("./stripe-client");
|
|
19
|
+
Object.defineProperty(exports, "StripeClient", { enumerable: true, get: function () { return stripe_client_1.StripeClient; } });
|
|
20
|
+
// ─── Rules Engine ─────────────────────────────────────────────────────────────
|
|
21
|
+
var rules_engine_1 = require("./rules-engine");
|
|
22
|
+
Object.defineProperty(exports, "SpendRules", { enumerable: true, get: function () { return rules_engine_1.SpendRules; } });
|
|
23
|
+
Object.defineProperty(exports, "evaluateRule", { enumerable: true, get: function () { return rules_engine_1.evaluateRule; } });
|
|
24
|
+
Object.defineProperty(exports, "evaluateAuthorization", { enumerable: true, get: function () { return rules_engine_1.evaluateAuthorization; } });
|
|
25
|
+
// ─── Transaction Tracker ──────────────────────────────────────────────────────
|
|
26
|
+
var tracker_1 = require("./tracker");
|
|
27
|
+
Object.defineProperty(exports, "TransactionTracker", { enumerable: true, get: function () { return tracker_1.TransactionTracker; } });
|
|
28
|
+
Object.defineProperty(exports, "tracker", { enumerable: true, get: function () { return tracker_1.tracker; } });
|
|
29
|
+
// ─── Rules Store ──────────────────────────────────────────────────────────────
|
|
30
|
+
var rules_store_1 = require("./rules-store");
|
|
31
|
+
Object.defineProperty(exports, "RulesStore", { enumerable: true, get: function () { return rules_store_1.RulesStore; } });
|
|
32
|
+
Object.defineProperty(exports, "rulesStore", { enumerable: true, get: function () { return rules_store_1.rulesStore; } });
|
|
33
|
+
// ─── Rule Validation ──────────────────────────────────────────────────────────
|
|
34
|
+
var rules_validation_1 = require("./rules-validation");
|
|
35
|
+
Object.defineProperty(exports, "validateRule", { enumerable: true, get: function () { return rules_validation_1.validateRule; } });
|
|
36
|
+
// ─── Test Utilities ───────────────────────────────────────────────────────────
|
|
37
|
+
var test_utils_1 = require("./test-utils");
|
|
38
|
+
Object.defineProperty(exports, "mockAuthorization", { enumerable: true, get: function () { return test_utils_1.mockAuthorization; } });
|
|
39
|
+
// ─── Webhook Handlers ─────────────────────────────────────────────────────────
|
|
40
|
+
var webhooks_1 = require("./webhooks");
|
|
41
|
+
Object.defineProperty(exports, "handleAuthorizationRequest", { enumerable: true, get: function () { return webhooks_1.handleAuthorizationRequest; } });
|
|
42
|
+
Object.defineProperty(exports, "handleAuthorizationCreated", { enumerable: true, get: function () { return webhooks_1.handleAuthorizationCreated; } });
|
|
43
|
+
Object.defineProperty(exports, "handleTransactionCreated", { enumerable: true, get: function () { return webhooks_1.handleTransactionCreated; } });
|
|
44
|
+
Object.defineProperty(exports, "handleCardUpdated", { enumerable: true, get: function () { return webhooks_1.handleCardUpdated; } });
|
|
45
|
+
Object.defineProperty(exports, "setReconciler", { enumerable: true, get: function () { return webhooks_1.setReconciler; } });
|
|
46
|
+
Object.defineProperty(exports, "getReconciler", { enumerable: true, get: function () { return webhooks_1.getReconciler; } });
|
|
47
|
+
Object.defineProperty(exports, "getRulesForCard", { enumerable: true, get: function () { return webhooks_1.getRulesForCard; } });
|
|
48
|
+
// ─── Database ─────────────────────────────────────────────────────────────────
|
|
49
|
+
var db_1 = require("./db");
|
|
50
|
+
Object.defineProperty(exports, "OpenCardDatabase", { enumerable: true, get: function () { return db_1.OpenCardDatabase; } });
|
|
51
|
+
Object.defineProperty(exports, "initDatabase", { enumerable: true, get: function () { return db_1.initDatabase; } });
|
|
52
|
+
// ─── Transaction Reconciler ───────────────────────────────────────────────────
|
|
53
|
+
var transaction_reconciler_1 = require("./transaction-reconciler");
|
|
54
|
+
Object.defineProperty(exports, "TransactionReconciler", { enumerable: true, get: function () { return transaction_reconciler_1.TransactionReconciler; } });
|
|
55
|
+
// ─── Logger ────────────────────────────────────────────────────────────────────
|
|
56
|
+
var logger_1 = require("./logger");
|
|
57
|
+
Object.defineProperty(exports, "getLogger", { enumerable: true, get: function () { return logger_1.getLogger; } });
|
|
58
|
+
Object.defineProperty(exports, "configureLogger", { enumerable: true, get: function () { return logger_1.configureLogger; } });
|
|
59
|
+
// ─── Error Classes ──────────────────────────────────────────────────────────────
|
|
60
|
+
var errors_1 = require("./errors");
|
|
61
|
+
Object.defineProperty(exports, "OpenCardError", { enumerable: true, get: function () { return errors_1.OpenCardError; } });
|
|
62
|
+
Object.defineProperty(exports, "wrapStripeError", { enumerable: true, get: function () { return errors_1.wrapStripeError; } });
|
|
63
|
+
Object.defineProperty(exports, "StripeAuthenticationError", { enumerable: true, get: function () { return errors_1.StripeAuthenticationError; } });
|
|
64
|
+
Object.defineProperty(exports, "RateLimitError", { enumerable: true, get: function () { return errors_1.RateLimitError; } });
|
|
65
|
+
Object.defineProperty(exports, "InvalidParameterError", { enumerable: true, get: function () { return errors_1.InvalidParameterError; } });
|
|
66
|
+
Object.defineProperty(exports, "RuleError", { enumerable: true, get: function () { return errors_1.RuleError; } });
|
|
67
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;GAYG;;;AAoBH,iFAAiF;AAEjF,iDAA+C;AAAtC,6GAAA,YAAY,OAAA;AAErB,iFAAiF;AAEjF,+CAAiF;AAAxE,0GAAA,UAAU,OAAA;AAAE,4GAAA,YAAY,OAAA;AAAE,qHAAA,qBAAqB,OAAA;AAGxD,iFAAiF;AAEjF,qCAAwD;AAA/C,6GAAA,kBAAkB,OAAA;AAAE,kGAAA,OAAO,OAAA;AAGpC,iFAAiF;AAEjF,6CAAuD;AAA9C,yGAAA,UAAU,OAAA;AAAE,yGAAA,UAAU,OAAA;AAE/B,iFAAiF;AAEjF,uDAAkD;AAAzC,gHAAA,YAAY,OAAA;AAGrB,iFAAiF;AAEjF,2CAAiD;AAAxC,+GAAA,iBAAiB,OAAA;AAG1B,iFAAiF;AAEjF,uCAQoB;AAPlB,sHAAA,0BAA0B,OAAA;AAC1B,sHAAA,0BAA0B,OAAA;AAC1B,oHAAA,wBAAwB,OAAA;AACxB,6GAAA,iBAAiB,OAAA;AACjB,yGAAA,aAAa,OAAA;AACb,yGAAA,aAAa,OAAA;AACb,2GAAA,eAAe,OAAA;AAIjB,iFAAiF;AAEjF,2BAAsD;AAA7C,sGAAA,gBAAgB,OAAA;AAAE,kGAAA,YAAY,OAAA;AAWvC,iFAAiF;AAEjF,mEAAiE;AAAxD,+HAAA,qBAAqB,OAAA;AAG9B,kFAAkF;AAElF,mCAAsD;AAA7C,mGAAA,SAAS,OAAA;AAAE,yGAAA,eAAe,OAAA;AAGnC,mFAAmF;AAEnF,mCAOkB;AANhB,uGAAA,aAAa,OAAA;AACb,yGAAA,eAAe,OAAA;AACf,mHAAA,yBAAyB,OAAA;AACzB,wGAAA,cAAc,OAAA;AACd,+GAAA,qBAAqB,OAAA;AACrB,mGAAA,SAAS,OAAA"}
|
package/dist/logger.d.ts
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structured Logger
|
|
3
|
+
* =================
|
|
4
|
+
* A minimal, zero-dependency structured logger for OpenCard.
|
|
5
|
+
*
|
|
6
|
+
* Outputs JSON in production, human-readable format in development.
|
|
7
|
+
* Components: stripe-client, rules-engine, webhook-server, tracker, rules-store
|
|
8
|
+
*
|
|
9
|
+
* Usage:
|
|
10
|
+
* const logger = getLogger('rules-engine');
|
|
11
|
+
* logger.info('evaluating rule', { ruleId, cardId, amount });
|
|
12
|
+
* logger.error('rule evaluation failed', { ruleId, error: err.message });
|
|
13
|
+
*/
|
|
14
|
+
export type LogLevel = 'debug' | 'info' | 'warn' | 'error';
|
|
15
|
+
export interface LogEntry {
|
|
16
|
+
timestamp: string;
|
|
17
|
+
level: LogLevel;
|
|
18
|
+
component: string;
|
|
19
|
+
message: string;
|
|
20
|
+
[key: string]: unknown;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Configuration for the logger.
|
|
24
|
+
* Allows switching between JSON (production) and pretty (development) modes.
|
|
25
|
+
*/
|
|
26
|
+
interface LoggerConfig {
|
|
27
|
+
/** Output format: 'json' or 'pretty' (default: detect from NODE_ENV) */
|
|
28
|
+
format?: 'json' | 'pretty';
|
|
29
|
+
/** Minimum log level to output (default: 'debug') */
|
|
30
|
+
minLevel?: LogLevel;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Configure the global logger.
|
|
34
|
+
*/
|
|
35
|
+
export declare function configureLogger(config: Partial<LoggerConfig>): void;
|
|
36
|
+
/**
|
|
37
|
+
* Get a logger for a specific component.
|
|
38
|
+
*
|
|
39
|
+
* @param component - Component name (e.g. 'stripe-client', 'rules-engine')
|
|
40
|
+
* @returns Logger instance with info, warn, error, debug methods
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* const logger = getLogger('rules-engine');
|
|
44
|
+
* logger.info('rule evaluated', { ruleId, decision: 'approved' });
|
|
45
|
+
*/
|
|
46
|
+
export declare function getLogger(component: string): {
|
|
47
|
+
debug: (message: string, context?: Record<string, unknown>) => void;
|
|
48
|
+
info: (message: string, context?: Record<string, unknown>) => void;
|
|
49
|
+
warn: (message: string, context?: Record<string, unknown>) => void;
|
|
50
|
+
error: (message: string, context?: Record<string, unknown>) => void;
|
|
51
|
+
};
|
|
52
|
+
export {};
|
|
53
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAE3D,MAAM,WAAW,QAAQ;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,QAAQ,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;;GAGG;AACH,UAAU,YAAY;IACpB,wEAAwE;IACxE,MAAM,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;IAC3B,qDAAqD;IACrD,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB;AAUD;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,IAAI,CAEnE;AAYD;;;;;;;;;GASG;AACH,wBAAgB,SAAS,CAAC,SAAS,EAAE,MAAM;qBA6BtB,MAAM,YAAY,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;oBAC1C,MAAM,YAAY,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;oBACzC,MAAM,YAAY,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;qBACxC,MAAM,YAAY,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;EAE7D"}
|
package/dist/logger.js
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Structured Logger
|
|
4
|
+
* =================
|
|
5
|
+
* A minimal, zero-dependency structured logger for OpenCard.
|
|
6
|
+
*
|
|
7
|
+
* Outputs JSON in production, human-readable format in development.
|
|
8
|
+
* Components: stripe-client, rules-engine, webhook-server, tracker, rules-store
|
|
9
|
+
*
|
|
10
|
+
* Usage:
|
|
11
|
+
* const logger = getLogger('rules-engine');
|
|
12
|
+
* logger.info('evaluating rule', { ruleId, cardId, amount });
|
|
13
|
+
* logger.error('rule evaluation failed', { ruleId, error: err.message });
|
|
14
|
+
*/
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.configureLogger = configureLogger;
|
|
17
|
+
exports.getLogger = getLogger;
|
|
18
|
+
/**
|
|
19
|
+
* Global logger configuration.
|
|
20
|
+
*/
|
|
21
|
+
let globalConfig = {
|
|
22
|
+
format: process.env.NODE_ENV === 'production' ? 'json' : 'pretty',
|
|
23
|
+
minLevel: 'debug',
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Configure the global logger.
|
|
27
|
+
*/
|
|
28
|
+
function configureLogger(config) {
|
|
29
|
+
globalConfig = { ...globalConfig, ...config };
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Check if a log level should be output.
|
|
33
|
+
*/
|
|
34
|
+
function shouldLog(level) {
|
|
35
|
+
const levels = ['debug', 'info', 'warn', 'error'];
|
|
36
|
+
const minIndex = levels.indexOf(globalConfig.minLevel || 'debug');
|
|
37
|
+
const currentIndex = levels.indexOf(level);
|
|
38
|
+
return currentIndex >= minIndex;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Get a logger for a specific component.
|
|
42
|
+
*
|
|
43
|
+
* @param component - Component name (e.g. 'stripe-client', 'rules-engine')
|
|
44
|
+
* @returns Logger instance with info, warn, error, debug methods
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* const logger = getLogger('rules-engine');
|
|
48
|
+
* logger.info('rule evaluated', { ruleId, decision: 'approved' });
|
|
49
|
+
*/
|
|
50
|
+
function getLogger(component) {
|
|
51
|
+
/**
|
|
52
|
+
* Format and output a log entry.
|
|
53
|
+
*/
|
|
54
|
+
const log = (level, message, context) => {
|
|
55
|
+
if (!shouldLog(level)) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
const entry = {
|
|
59
|
+
timestamp: new Date().toISOString(),
|
|
60
|
+
level,
|
|
61
|
+
component,
|
|
62
|
+
message,
|
|
63
|
+
...(context || {}),
|
|
64
|
+
};
|
|
65
|
+
const output = globalConfig.format === 'json'
|
|
66
|
+
? formatJSON(entry)
|
|
67
|
+
: formatPretty(entry);
|
|
68
|
+
// Use the appropriate console method for the level
|
|
69
|
+
const consoleMethod = level === 'error' ? console.error :
|
|
70
|
+
level === 'warn' ? console.warn :
|
|
71
|
+
console.log;
|
|
72
|
+
consoleMethod(output);
|
|
73
|
+
};
|
|
74
|
+
return {
|
|
75
|
+
debug: (message, context) => log('debug', message, context),
|
|
76
|
+
info: (message, context) => log('info', message, context),
|
|
77
|
+
warn: (message, context) => log('warn', message, context),
|
|
78
|
+
error: (message, context) => log('error', message, context),
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Format a log entry as JSON.
|
|
83
|
+
*/
|
|
84
|
+
function formatJSON(entry) {
|
|
85
|
+
return JSON.stringify(entry);
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Format a log entry as human-readable text.
|
|
89
|
+
*/
|
|
90
|
+
function formatPretty(entry) {
|
|
91
|
+
const levelEmoji = {
|
|
92
|
+
debug: '🔍',
|
|
93
|
+
info: 'ℹ',
|
|
94
|
+
warn: '⚠',
|
|
95
|
+
error: '❌',
|
|
96
|
+
};
|
|
97
|
+
const timestamp = new Date(entry.timestamp).toLocaleTimeString();
|
|
98
|
+
const level = entry.level.toUpperCase().padEnd(5);
|
|
99
|
+
const emoji = levelEmoji[entry.level];
|
|
100
|
+
const component = `[${entry.component}]`.padEnd(20);
|
|
101
|
+
// Format context as key=value pairs
|
|
102
|
+
const contextEntries = Object.entries(entry)
|
|
103
|
+
.filter(([key]) => !['timestamp', 'level', 'component', 'message'].includes(key))
|
|
104
|
+
.map(([key, value]) => `${key}=${typeof value === 'string' ? value : JSON.stringify(value)}`)
|
|
105
|
+
.join(' | ');
|
|
106
|
+
const contextStr = contextEntries ? ` | ${contextEntries}` : '';
|
|
107
|
+
return `${emoji} ${timestamp} ${level} ${component} ${entry.message}${contextStr}`;
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rules Engine
|
|
3
|
+
* ============
|
|
4
|
+
* Two responsibilities:
|
|
5
|
+
*
|
|
6
|
+
* 1. SpendRules — a fluent builder that makes it easy to construct SpendRule
|
|
7
|
+
* objects without remembering field names. Also ships pre-built templates
|
|
8
|
+
* for common agent configurations.
|
|
9
|
+
*
|
|
10
|
+
* 2. evaluateAuthorization — takes a live Stripe authorization request plus
|
|
11
|
+
* a card's rules and returns an approve/decline decision. This is called
|
|
12
|
+
* from the webhook handler in real time (within the ~2s Stripe window).
|
|
13
|
+
*
|
|
14
|
+
* All amounts are in cents throughout. Stripe uses cents; we match that to
|
|
15
|
+
* avoid any float-to-dollar conversion bugs.
|
|
16
|
+
*
|
|
17
|
+
* ─── Design philosophy ───────────────────────────────────────────────────────
|
|
18
|
+
* The rules engine enforces two core hard controls:
|
|
19
|
+
* 1. Spend limits (daily, monthly, per-transaction)
|
|
20
|
+
* 2. Category locks (allowed/blocked merchant categories)
|
|
21
|
+
*
|
|
22
|
+
* Confidence scoring — where agents self-report how sure they are about a
|
|
23
|
+
* purchase — was deliberately removed. Self-reported confidence is unreliable:
|
|
24
|
+
* an agent with no safety awareness will report 1.0; a cautious agent might
|
|
25
|
+
* report 0.7 for a perfectly reasonable purchase. It adds noise without
|
|
26
|
+
* adding real safety. Hard limits are the guardrail. Category locks add
|
|
27
|
+
* specificity. That's the model.
|
|
28
|
+
*/
|
|
29
|
+
import Stripe from 'stripe';
|
|
30
|
+
import { SpendRule, SpendRuleTemplate } from './types';
|
|
31
|
+
export declare class SpendRules {
|
|
32
|
+
private rule;
|
|
33
|
+
/**
|
|
34
|
+
* Create a new SpendRules builder
|
|
35
|
+
*/
|
|
36
|
+
constructor();
|
|
37
|
+
/**
|
|
38
|
+
* Load a pre-built template
|
|
39
|
+
*/
|
|
40
|
+
static template(template: SpendRuleTemplate): SpendRules;
|
|
41
|
+
/**
|
|
42
|
+
* Set allowed merchant categories
|
|
43
|
+
* Only transactions in these categories will be approved
|
|
44
|
+
*/
|
|
45
|
+
category(categories: string[]): SpendRules;
|
|
46
|
+
/**
|
|
47
|
+
* Set blocked merchant categories
|
|
48
|
+
* Transactions in these categories will be declined
|
|
49
|
+
*/
|
|
50
|
+
blockCategory(categories: string[]): SpendRules;
|
|
51
|
+
/**
|
|
52
|
+
* Set maximum amount per transaction (in cents)
|
|
53
|
+
*/
|
|
54
|
+
maxPerTx(cents: number): SpendRules;
|
|
55
|
+
/**
|
|
56
|
+
* Set daily spending limit (in cents)
|
|
57
|
+
*/
|
|
58
|
+
dailyLimit(cents: number): SpendRules;
|
|
59
|
+
/**
|
|
60
|
+
* Set monthly spending limit (in cents)
|
|
61
|
+
*/
|
|
62
|
+
monthlyLimit(cents: number): SpendRules;
|
|
63
|
+
/**
|
|
64
|
+
* Set per-authorization limit (in cents)
|
|
65
|
+
*/
|
|
66
|
+
perAuthLimit(cents: number): SpendRules;
|
|
67
|
+
/**
|
|
68
|
+
* Set whether transactions above the approval threshold require human sign-off.
|
|
69
|
+
* Usually you don't call this directly — `approvalThreshold()` sets it automatically.
|
|
70
|
+
* But you can call it explicitly if you need to toggle approval requirements
|
|
71
|
+
* independently of the threshold value.
|
|
72
|
+
*/
|
|
73
|
+
requiresApproval(required: boolean): SpendRules;
|
|
74
|
+
/**
|
|
75
|
+
* Set approval threshold (in cents)
|
|
76
|
+
* Transactions above this amount require human approval.
|
|
77
|
+
* Also sets requiresApproval = true automatically.
|
|
78
|
+
*/
|
|
79
|
+
approvalThreshold(cents: number): SpendRules;
|
|
80
|
+
/**
|
|
81
|
+
* Set failure handling behavior.
|
|
82
|
+
*
|
|
83
|
+
* Currently only 'decline' is fully implemented in the authorization flow.
|
|
84
|
+
* 'alert' and 'pause' are accepted for forward compatibility but behave
|
|
85
|
+
* the same as 'decline' today — the charge is declined. These modes will
|
|
86
|
+
* be wired to notification and card-pausing logic in a future release.
|
|
87
|
+
*/
|
|
88
|
+
onFailure(action: 'decline' | 'alert' | 'pause'): SpendRules;
|
|
89
|
+
/**
|
|
90
|
+
* Set human-readable name for this rule set
|
|
91
|
+
*/
|
|
92
|
+
name(name: string): SpendRules;
|
|
93
|
+
/**
|
|
94
|
+
* Set human-readable description for this rule set
|
|
95
|
+
*/
|
|
96
|
+
description(desc: string): SpendRules;
|
|
97
|
+
/**
|
|
98
|
+
* Build and return the final SpendRule object
|
|
99
|
+
*/
|
|
100
|
+
build(): SpendRule;
|
|
101
|
+
/**
|
|
102
|
+
* Get a string representation of the rules
|
|
103
|
+
*/
|
|
104
|
+
toString(): string;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Evaluate a transaction against a rule set
|
|
108
|
+
* Returns { allowed: boolean, reason?: string }
|
|
109
|
+
*/
|
|
110
|
+
export declare function evaluateRule(rule: SpendRule, transaction: {
|
|
111
|
+
amount: number;
|
|
112
|
+
category?: string;
|
|
113
|
+
}): {
|
|
114
|
+
allowed: boolean;
|
|
115
|
+
reason?: string;
|
|
116
|
+
};
|
|
117
|
+
/**
|
|
118
|
+
* The decision returned by evaluateAuthorization.
|
|
119
|
+
* `approved` goes directly into the Stripe webhook response.
|
|
120
|
+
* `reason` is logged for debugging and audit purposes.
|
|
121
|
+
*/
|
|
122
|
+
export interface AuthorizationDecision {
|
|
123
|
+
approved: boolean;
|
|
124
|
+
reason: string;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Current spend context passed into evaluateAuthorization.
|
|
128
|
+
* The caller (webhook handler) retrieves these from the tracker and passes
|
|
129
|
+
* them in, keeping the rules engine pure and easy to test without mocking
|
|
130
|
+
* any global state.
|
|
131
|
+
*/
|
|
132
|
+
export interface SpendContext {
|
|
133
|
+
/** How many cents the card has spent today (UTC calendar day). */
|
|
134
|
+
dailySpend: number;
|
|
135
|
+
/** How many cents the card has spent this calendar month (UTC). */
|
|
136
|
+
monthlySpend: number;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* evaluateAuthorization
|
|
140
|
+
* ──────────────────────
|
|
141
|
+
* The core decision function. Given a live Stripe authorization request and
|
|
142
|
+
* the card's spending rules, determines whether to approve or decline.
|
|
143
|
+
*
|
|
144
|
+
* Rules are checked in order of cheapest/fastest first:
|
|
145
|
+
* 1. Merchant category (allowed list, then blocked list)
|
|
146
|
+
* 2. Per-transaction amount limit
|
|
147
|
+
* 3. Daily budget (current spend + this tx > limit?)
|
|
148
|
+
* 4. Monthly budget
|
|
149
|
+
*
|
|
150
|
+
* The first failing check short-circuits and returns a decline with a reason
|
|
151
|
+
* string that explains exactly which rule tripped.
|
|
152
|
+
*
|
|
153
|
+
* @param auth - The Stripe Issuing.Authorization from the webhook event
|
|
154
|
+
* @param rules - The SpendRule configured for this card
|
|
155
|
+
* @param context - Current spend totals from the tracker
|
|
156
|
+
* @returns AuthorizationDecision with approved flag and human-readable reason
|
|
157
|
+
*/
|
|
158
|
+
export declare function evaluateAuthorization(auth: Stripe.Issuing.Authorization, rules: SpendRule, context: SpendContext): AuthorizationDecision;
|
|
159
|
+
//# sourceMappingURL=rules-engine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rules-engine.d.ts","sourceRoot":"","sources":["../src/rules-engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,MAAM,MAAM,QAAQ,CAAC;AAE5B,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAIvD,qBAAa,UAAU;IACrB,OAAO,CAAC,IAAI,CAAiB;IAE7B;;OAEG;;IAKH;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE,iBAAiB,GAAG,UAAU;IAmDxD;;;OAGG;IACH,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,UAAU;IAK1C;;;OAGG;IACH,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,UAAU;IAK/C;;OAEG;IACH,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU;IAQnC;;OAEG;IACH,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU;IASrC;;OAEG;IACH,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU;IASvC;;OAEG;IACH,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU;IASvC;;;;;OAKG;IACH,gBAAgB,CAAC,QAAQ,EAAE,OAAO,GAAG,UAAU;IAK/C;;;;OAIG;IACH,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU;IAS5C;;;;;;;OAOG;IACH,SAAS,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,GAAG,OAAO,GAAG,UAAU;IAK5D;;OAEG;IACH,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU;IAK9B;;OAEG;IACH,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU;IAKrC;;OAEG;IACH,KAAK,IAAI,SAAS;IASlB;;OAEG;IACH,QAAQ,IAAI,MAAM;CAiCnB;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,SAAS,EACf,WAAW,EAAE;IACX,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,GACA;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAwCvC;AAID;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IAC3B,kEAAkE;IAClE,UAAU,EAAE,MAAM,CAAC;IACnB,mEAAmE;IACnE,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,aAAa,EAClC,KAAK,EAAE,SAAS,EAChB,OAAO,EAAE,YAAY,GACpB,qBAAqB,CAuFvB"}
|