@mj-biz-apps/orders-core-entities-server 0.0.1 → 5.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +183 -0
- package/README.md +141 -2
- package/dist/AccountingBridge.d.ts +65 -0
- package/dist/AccountingBridge.d.ts.map +1 -0
- package/dist/AccountingBridge.js +102 -0
- package/dist/AccountingBridge.js.map +1 -0
- package/dist/AdvanceOrderStateOperation.d.ts +80 -0
- package/dist/AdvanceOrderStateOperation.d.ts.map +1 -0
- package/dist/AdvanceOrderStateOperation.js +267 -0
- package/dist/AdvanceOrderStateOperation.js.map +1 -0
- package/dist/ApplyAccountCreditOperation.d.ts +97 -0
- package/dist/ApplyAccountCreditOperation.d.ts.map +1 -0
- package/dist/ApplyAccountCreditOperation.js +275 -0
- package/dist/ApplyAccountCreditOperation.js.map +1 -0
- package/dist/BaseDeliveryChannel.d.ts +106 -0
- package/dist/BaseDeliveryChannel.d.ts.map +1 -0
- package/dist/BaseDeliveryChannel.js +36 -0
- package/dist/BaseDeliveryChannel.js.map +1 -0
- package/dist/BasePaymentProvider.d.ts +239 -0
- package/dist/BasePaymentProvider.d.ts.map +1 -0
- package/dist/BasePaymentProvider.js +91 -0
- package/dist/BasePaymentProvider.js.map +1 -0
- package/dist/BundleBehavior.d.ts +139 -0
- package/dist/BundleBehavior.d.ts.map +1 -0
- package/dist/BundleBehavior.js +173 -0
- package/dist/BundleBehavior.js.map +1 -0
- package/dist/BundleEngine.d.ts +60 -0
- package/dist/BundleEngine.d.ts.map +1 -0
- package/dist/BundleEngine.js +197 -0
- package/dist/BundleEngine.js.map +1 -0
- package/dist/CancelSubscriptionOperation.d.ts +98 -0
- package/dist/CancelSubscriptionOperation.d.ts.map +1 -0
- package/dist/CancelSubscriptionOperation.js +317 -0
- package/dist/CancelSubscriptionOperation.js.map +1 -0
- package/dist/CapturePaymentOperation.d.ts +62 -0
- package/dist/CapturePaymentOperation.d.ts.map +1 -0
- package/dist/CapturePaymentOperation.js +463 -0
- package/dist/CapturePaymentOperation.js.map +1 -0
- package/dist/CheckEntitlementOperation.d.ts +27 -0
- package/dist/CheckEntitlementOperation.d.ts.map +1 -0
- package/dist/CheckEntitlementOperation.js +45 -0
- package/dist/CheckEntitlementOperation.js.map +1 -0
- package/dist/CheckoutSessionService.d.ts +258 -0
- package/dist/CheckoutSessionService.d.ts.map +1 -0
- package/dist/CheckoutSessionService.js +1557 -0
- package/dist/CheckoutSessionService.js.map +1 -0
- package/dist/DeliveryBehavior.d.ts +121 -0
- package/dist/DeliveryBehavior.d.ts.map +1 -0
- package/dist/DeliveryBehavior.js +145 -0
- package/dist/DeliveryBehavior.js.map +1 -0
- package/dist/DeliveryRecipientResolver.d.ts +38 -0
- package/dist/DeliveryRecipientResolver.d.ts.map +1 -0
- package/dist/DeliveryRecipientResolver.js +93 -0
- package/dist/DeliveryRecipientResolver.js.map +1 -0
- package/dist/DeliveryResolver.d.ts +14 -0
- package/dist/DeliveryResolver.d.ts.map +1 -0
- package/dist/DeliveryResolver.js +45 -0
- package/dist/DeliveryResolver.js.map +1 -0
- package/dist/EmailDeliveryChannel.d.ts +31 -0
- package/dist/EmailDeliveryChannel.d.ts.map +1 -0
- package/dist/EmailDeliveryChannel.js +158 -0
- package/dist/EmailDeliveryChannel.js.map +1 -0
- package/dist/EntitlementBehavior.d.ts +235 -0
- package/dist/EntitlementBehavior.d.ts.map +1 -0
- package/dist/EntitlementBehavior.js +330 -0
- package/dist/EntitlementBehavior.js.map +1 -0
- package/dist/EntitlementEngine.d.ts +97 -0
- package/dist/EntitlementEngine.d.ts.map +1 -0
- package/dist/EntitlementEngine.js +338 -0
- package/dist/EntitlementEngine.js.map +1 -0
- package/dist/EntitlementGrantClaimDriver.d.ts +42 -0
- package/dist/EntitlementGrantClaimDriver.d.ts.map +1 -0
- package/dist/EntitlementGrantClaimDriver.js +158 -0
- package/dist/EntitlementGrantClaimDriver.js.map +1 -0
- package/dist/EntitlementRead.d.ts +82 -0
- package/dist/EntitlementRead.d.ts.map +1 -0
- package/dist/EntitlementRead.js +368 -0
- package/dist/EntitlementRead.js.map +1 -0
- package/dist/FulfillOrderLinesOperation.d.ts +34 -0
- package/dist/FulfillOrderLinesOperation.d.ts.map +1 -0
- package/dist/FulfillOrderLinesOperation.js +208 -0
- package/dist/FulfillOrderLinesOperation.js.map +1 -0
- package/dist/FulfillmentBehavior.d.ts +101 -0
- package/dist/FulfillmentBehavior.d.ts.map +1 -0
- package/dist/FulfillmentBehavior.js +145 -0
- package/dist/FulfillmentBehavior.js.map +1 -0
- package/dist/GLAccountResolver.d.ts +123 -0
- package/dist/GLAccountResolver.d.ts.map +1 -0
- package/dist/GLAccountResolver.js +175 -0
- package/dist/GLAccountResolver.js.map +1 -0
- package/dist/GetFulfillmentQueueOperation.d.ts +35 -0
- package/dist/GetFulfillmentQueueOperation.d.ts.map +1 -0
- package/dist/GetFulfillmentQueueOperation.js +221 -0
- package/dist/GetFulfillmentQueueOperation.js.map +1 -0
- package/dist/GetOverdueWorklistOperation.d.ts +41 -0
- package/dist/GetOverdueWorklistOperation.d.ts.map +1 -0
- package/dist/GetOverdueWorklistOperation.js +210 -0
- package/dist/GetOverdueWorklistOperation.js.map +1 -0
- package/dist/GiftCardBehavior.d.ts +97 -0
- package/dist/GiftCardBehavior.d.ts.map +1 -0
- package/dist/GiftCardBehavior.js +121 -0
- package/dist/GiftCardBehavior.js.map +1 -0
- package/dist/GiftCardEngine.d.ts +59 -0
- package/dist/GiftCardEngine.d.ts.map +1 -0
- package/dist/GiftCardEngine.js +197 -0
- package/dist/GiftCardEngine.js.map +1 -0
- package/dist/GuestOrderClaimDriver.d.ts +36 -0
- package/dist/GuestOrderClaimDriver.d.ts.map +1 -0
- package/dist/GuestOrderClaimDriver.js +161 -0
- package/dist/GuestOrderClaimDriver.js.map +1 -0
- package/dist/InvoiceBehavior.d.ts +394 -0
- package/dist/InvoiceBehavior.d.ts.map +1 -0
- package/dist/InvoiceBehavior.js +496 -0
- package/dist/InvoiceBehavior.js.map +1 -0
- package/dist/InvoiceBuilder.d.ts +48 -0
- package/dist/InvoiceBuilder.d.ts.map +1 -0
- package/dist/InvoiceBuilder.js +352 -0
- package/dist/InvoiceBuilder.js.map +1 -0
- package/dist/InvoiceDisplay.d.ts +96 -0
- package/dist/InvoiceDisplay.d.ts.map +1 -0
- package/dist/InvoiceDisplay.js +121 -0
- package/dist/InvoiceDisplay.js.map +1 -0
- package/dist/ListEntitlementsOperation.d.ts +21 -0
- package/dist/ListEntitlementsOperation.d.ts.map +1 -0
- package/dist/ListEntitlementsOperation.js +39 -0
- package/dist/ListEntitlementsOperation.js.map +1 -0
- package/dist/ManualPaymentProvider.d.ts +19 -0
- package/dist/ManualPaymentProvider.d.ts.map +1 -0
- package/dist/ManualPaymentProvider.js +92 -0
- package/dist/ManualPaymentProvider.js.map +1 -0
- package/dist/OrderEntityServer.d.ts +542 -0
- package/dist/OrderEntityServer.d.ts.map +1 -0
- package/dist/OrderEntityServer.js +2100 -0
- package/dist/OrderEntityServer.js.map +1 -0
- package/dist/OrderJournalEntryFactory.d.ts +140 -0
- package/dist/OrderJournalEntryFactory.d.ts.map +1 -0
- package/dist/OrderJournalEntryFactory.js +466 -0
- package/dist/OrderJournalEntryFactory.js.map +1 -0
- package/dist/OrderLineEntityServer.d.ts +90 -0
- package/dist/OrderLineEntityServer.d.ts.map +1 -0
- package/dist/OrderLineEntityServer.js +260 -0
- package/dist/OrderLineEntityServer.js.map +1 -0
- package/dist/OrdersSettings.d.ts +36 -0
- package/dist/OrdersSettings.d.ts.map +1 -0
- package/dist/OrdersSettings.js +147 -0
- package/dist/OrdersSettings.js.map +1 -0
- package/dist/PaymentAllocationFactory.d.ts +128 -0
- package/dist/PaymentAllocationFactory.d.ts.map +1 -0
- package/dist/PaymentAllocationFactory.js +235 -0
- package/dist/PaymentAllocationFactory.js.map +1 -0
- package/dist/PaymentHeaderEntityServer.d.ts +180 -0
- package/dist/PaymentHeaderEntityServer.d.ts.map +1 -0
- package/dist/PaymentHeaderEntityServer.js +656 -0
- package/dist/PaymentHeaderEntityServer.js.map +1 -0
- package/dist/PaymentIntentService.d.ts +101 -0
- package/dist/PaymentIntentService.d.ts.map +1 -0
- package/dist/PaymentIntentService.js +150 -0
- package/dist/PaymentIntentService.js.map +1 -0
- package/dist/PaymentJournalEntryFactory.d.ts +99 -0
- package/dist/PaymentJournalEntryFactory.d.ts.map +1 -0
- package/dist/PaymentJournalEntryFactory.js +127 -0
- package/dist/PaymentJournalEntryFactory.js.map +1 -0
- package/dist/PaymentLineEntityServer.d.ts +73 -0
- package/dist/PaymentLineEntityServer.d.ts.map +1 -0
- package/dist/PaymentLineEntityServer.js +303 -0
- package/dist/PaymentLineEntityServer.js.map +1 -0
- package/dist/PaymentProviderBehavior.d.ts +222 -0
- package/dist/PaymentProviderBehavior.d.ts.map +1 -0
- package/dist/PaymentProviderBehavior.js +368 -0
- package/dist/PaymentProviderBehavior.js.map +1 -0
- package/dist/PaymentProviderResolver.d.ts +84 -0
- package/dist/PaymentProviderResolver.d.ts.map +1 -0
- package/dist/PaymentProviderResolver.js +220 -0
- package/dist/PaymentProviderResolver.js.map +1 -0
- package/dist/PaymentReversalFactory.d.ts +107 -0
- package/dist/PaymentReversalFactory.d.ts.map +1 -0
- package/dist/PaymentReversalFactory.js +174 -0
- package/dist/PaymentReversalFactory.js.map +1 -0
- package/dist/PaymentSettlement.d.ts +56 -0
- package/dist/PaymentSettlement.d.ts.map +1 -0
- package/dist/PaymentSettlement.js +243 -0
- package/dist/PaymentSettlement.js.map +1 -0
- package/dist/PaymentTermsBehavior.d.ts +109 -0
- package/dist/PaymentTermsBehavior.d.ts.map +1 -0
- package/dist/PaymentTermsBehavior.js +172 -0
- package/dist/PaymentTermsBehavior.js.map +1 -0
- package/dist/PaymentWebhookHandler.d.ts +103 -0
- package/dist/PaymentWebhookHandler.d.ts.map +1 -0
- package/dist/PaymentWebhookHandler.js +246 -0
- package/dist/PaymentWebhookHandler.js.map +1 -0
- package/dist/PreviewPriceOperation.d.ts +62 -0
- package/dist/PreviewPriceOperation.d.ts.map +1 -0
- package/dist/PreviewPriceOperation.js +161 -0
- package/dist/PreviewPriceOperation.js.map +1 -0
- package/dist/PriceOrderOperation.d.ts +93 -0
- package/dist/PriceOrderOperation.d.ts.map +1 -0
- package/dist/PriceOrderOperation.js +146 -0
- package/dist/PriceOrderOperation.js.map +1 -0
- package/dist/ProductPriceEntityServer.d.ts +34 -0
- package/dist/ProductPriceEntityServer.d.ts.map +1 -0
- package/dist/ProductPriceEntityServer.js +97 -0
- package/dist/ProductPriceEntityServer.js.map +1 -0
- package/dist/RefundPaymentOperation.d.ts +61 -0
- package/dist/RefundPaymentOperation.d.ts.map +1 -0
- package/dist/RefundPaymentOperation.js +177 -0
- package/dist/RefundPaymentOperation.js.map +1 -0
- package/dist/RevenueRecognition.d.ts +76 -0
- package/dist/RevenueRecognition.d.ts.map +1 -0
- package/dist/RevenueRecognition.js +133 -0
- package/dist/RevenueRecognition.js.map +1 -0
- package/dist/ReversalBehavior.d.ts +82 -0
- package/dist/ReversalBehavior.d.ts.map +1 -0
- package/dist/ReversalBehavior.js +100 -0
- package/dist/ReversalBehavior.js.map +1 -0
- package/dist/ReversalResolver.d.ts +37 -0
- package/dist/ReversalResolver.d.ts.map +1 -0
- package/dist/ReversalResolver.js +96 -0
- package/dist/ReversalResolver.js.map +1 -0
- package/dist/SpawnRenewalsOperation.d.ts +109 -0
- package/dist/SpawnRenewalsOperation.d.ts.map +1 -0
- package/dist/SpawnRenewalsOperation.js +295 -0
- package/dist/SpawnRenewalsOperation.js.map +1 -0
- package/dist/StoredValuePaymentProvider.d.ts +52 -0
- package/dist/StoredValuePaymentProvider.d.ts.map +1 -0
- package/dist/StoredValuePaymentProvider.js +205 -0
- package/dist/StoredValuePaymentProvider.js.map +1 -0
- package/dist/StripeACHPaymentProvider.d.ts +50 -0
- package/dist/StripeACHPaymentProvider.d.ts.map +1 -0
- package/dist/StripeACHPaymentProvider.js +211 -0
- package/dist/StripeACHPaymentProvider.js.map +1 -0
- package/dist/StripePaymentProvider.d.ts +83 -0
- package/dist/StripePaymentProvider.d.ts.map +1 -0
- package/dist/StripePaymentProvider.js +442 -0
- package/dist/StripePaymentProvider.js.map +1 -0
- package/dist/SubscriptionBehavior.d.ts +197 -0
- package/dist/SubscriptionBehavior.d.ts.map +1 -0
- package/dist/SubscriptionBehavior.js +415 -0
- package/dist/SubscriptionBehavior.js.map +1 -0
- package/dist/checkoutCaptureAlert.d.ts +16 -0
- package/dist/checkoutCaptureAlert.d.ts.map +1 -0
- package/dist/checkoutCaptureAlert.js +55 -0
- package/dist/checkoutCaptureAlert.js.map +1 -0
- package/dist/checkoutCaptureRetry.d.ts +27 -0
- package/dist/checkoutCaptureRetry.d.ts.map +1 -0
- package/dist/checkoutCaptureRetry.js +50 -0
- package/dist/checkoutCaptureRetry.js.map +1 -0
- package/dist/claimDriverHelpers.d.ts +15 -0
- package/dist/claimDriverHelpers.d.ts.map +1 -0
- package/dist/claimDriverHelpers.js +34 -0
- package/dist/claimDriverHelpers.js.map +1 -0
- package/dist/entity-names.d.ts +15 -0
- package/dist/entity-names.d.ts.map +1 -0
- package/dist/entity-names.js +15 -0
- package/dist/entity-names.js.map +1 -0
- package/dist/identityClaimContracts.d.ts +118 -0
- package/dist/identityClaimContracts.d.ts.map +1 -0
- package/dist/identityClaimContracts.js +58 -0
- package/dist/identityClaimContracts.js.map +1 -0
- package/dist/index.d.ts +126 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +115 -0
- package/dist/index.js.map +1 -0
- package/dist/sql-guards.d.ts +78 -0
- package/dist/sql-guards.d.ts.map +1 -0
- package/dist/sql-guards.js +115 -0
- package/dist/sql-guards.js.map +1 -0
- package/package.json +50 -5
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Validation for values that reach SQL text — applied at the
|
|
3
|
+
* operation boundary.
|
|
4
|
+
*
|
|
5
|
+
* THE PROBLEM. `RunView`'s `ExtraFilter` is composed as SQL, and this codebase
|
|
6
|
+
* builds filters by interpolating ids into template strings. That is safe for the
|
|
7
|
+
* overwhelming majority of sites, where the id was read out of the database a
|
|
8
|
+
* moment earlier and is a UUID by construction. It is NOT safe for the handful of
|
|
9
|
+
* values that arrive from a REMOTE CALLER: a remote operation's input is whatever
|
|
10
|
+
* the caller sent.
|
|
11
|
+
*
|
|
12
|
+
* WHY GUARD AT THE BOUNDARY RATHER THAN AT EVERY FILTER. An id from a caller is
|
|
13
|
+
* passed down through loaders and resolvers before it reaches a filter, sometimes
|
|
14
|
+
* several frames deep. Guarding each filter site would mean auditing every path a
|
|
15
|
+
* value can take and re-auditing it whenever someone adds a new one. Validating
|
|
16
|
+
* once, where untrusted data enters, makes everything downstream trusted by
|
|
17
|
+
* construction — and it is a single line per operation that a reviewer can check.
|
|
18
|
+
*
|
|
19
|
+
* WHY REJECT RATHER THAN ESCAPE. Doubling quotes would let a malformed id through
|
|
20
|
+
* to a query that then returns nothing, or worse, something. A caller that sends a
|
|
21
|
+
* non-UUID where a UUID belongs has a bug, and the useful response is to say so.
|
|
22
|
+
* Silently returning the wrong rows is the failure mode worth designing against:
|
|
23
|
+
* an injected `' OR 1=1 --` in a customer filter widens a result set rather than
|
|
24
|
+
* breaking it, so it reads as working software while disclosing other people's data.
|
|
25
|
+
*
|
|
26
|
+
* @module @mj-biz-apps/orders-core-entities-server
|
|
27
|
+
*/
|
|
28
|
+
/** Raised when caller-supplied input cannot safely reach a filter. */
|
|
29
|
+
export declare class InvalidOperationInputError extends Error {
|
|
30
|
+
constructor(message: string);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Require a UUID, or throw.
|
|
34
|
+
*
|
|
35
|
+
* @param value The caller-supplied value.
|
|
36
|
+
* @param field Field name, used in the error so the caller can find their mistake.
|
|
37
|
+
* @returns The value, unchanged, once it is known to be a UUID.
|
|
38
|
+
* @throws {InvalidOperationInputError} If it is not a UUID.
|
|
39
|
+
*/
|
|
40
|
+
export declare function RequireUUID(value: string, field: string): string;
|
|
41
|
+
/**
|
|
42
|
+
* Require a UUID when present. Absent stays absent — many id inputs are optional
|
|
43
|
+
* filters, and an omitted filter is not an invalid one.
|
|
44
|
+
*/
|
|
45
|
+
export declare function RequireOptionalUUID<T extends string | null | undefined>(value: T, field: string): T;
|
|
46
|
+
/** Require every element of an id list to be a UUID. */
|
|
47
|
+
export declare function RequireUUIDs(values: string[] | null | undefined, field: string): string[];
|
|
48
|
+
/**
|
|
49
|
+
* Require an ISO date, returning just the `YYYY-MM-DD` portion.
|
|
50
|
+
*
|
|
51
|
+
* Dates are interpolated into comparisons, so they carry the same risk as ids.
|
|
52
|
+
* Truncating to the date part is deliberate: these filters compare days.
|
|
53
|
+
*/
|
|
54
|
+
export declare function RequireDate(value: string, field: string): string;
|
|
55
|
+
/**
|
|
56
|
+
* Escape a free-text value for a SQL string literal.
|
|
57
|
+
*
|
|
58
|
+
* For the values that are legitimately text rather than ids — a provider's refund
|
|
59
|
+
* reference, a search term. Doubling the quote is the SQL Server escape.
|
|
60
|
+
*/
|
|
61
|
+
export declare function EscapeText(value: string): string;
|
|
62
|
+
/**
|
|
63
|
+
* LOCAL FALLBACK for `EscapeSQLString` from `@memberjunction/global`.
|
|
64
|
+
*
|
|
65
|
+
* CLAUDE.md requires this function for SQL string escaping, but no published
|
|
66
|
+
* `@memberjunction/global` exports it — `6.1.0-edge.3` ships `Escape` and `EscapeHTML`
|
|
67
|
+
* and nothing else. Following the rule as written therefore broke the build. This keeps
|
|
68
|
+
* the rule followable at the call sites until MJ publishes the real one; delete it then
|
|
69
|
+
* and re-point `claimDriverHelpers.ts` and `GuestOrderClaimDriver.ts` at the package.
|
|
70
|
+
*
|
|
71
|
+
* Stricter than {@link EscapeText} on two counts, both of which CLAUDE.md calls out as
|
|
72
|
+
* the reasons to prefer `EscapeSQLString`: `null`/`undefined` become an empty string
|
|
73
|
+
* rather than the literal text `"null"`, and embedded null bytes are stripped — SQL
|
|
74
|
+
* Server truncates at `\0`, so a value carrying one can end a quoted literal early and
|
|
75
|
+
* leave the remainder of the input parsed as SQL.
|
|
76
|
+
*/
|
|
77
|
+
export declare function EscapeSQLString(value: string | null | undefined): string;
|
|
78
|
+
//# sourceMappingURL=sql-guards.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sql-guards.d.ts","sourceRoot":"","sources":["../src/sql-guards.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAIH,sEAAsE;AACtE,qBAAa,0BAA2B,SAAQ,KAAK;gBACrC,OAAO,EAAE,MAAM;CAI9B;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAKhE;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,SAAS,MAAM,GAAG,IAAI,GAAG,SAAS,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,GAAG,CAAC,CAInG;AAED,wDAAwD;AACxD,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,GAAG,SAAS,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAGzF;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAYhE;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAKxE"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Validation for values that reach SQL text — applied at the
|
|
3
|
+
* operation boundary.
|
|
4
|
+
*
|
|
5
|
+
* THE PROBLEM. `RunView`'s `ExtraFilter` is composed as SQL, and this codebase
|
|
6
|
+
* builds filters by interpolating ids into template strings. That is safe for the
|
|
7
|
+
* overwhelming majority of sites, where the id was read out of the database a
|
|
8
|
+
* moment earlier and is a UUID by construction. It is NOT safe for the handful of
|
|
9
|
+
* values that arrive from a REMOTE CALLER: a remote operation's input is whatever
|
|
10
|
+
* the caller sent.
|
|
11
|
+
*
|
|
12
|
+
* WHY GUARD AT THE BOUNDARY RATHER THAN AT EVERY FILTER. An id from a caller is
|
|
13
|
+
* passed down through loaders and resolvers before it reaches a filter, sometimes
|
|
14
|
+
* several frames deep. Guarding each filter site would mean auditing every path a
|
|
15
|
+
* value can take and re-auditing it whenever someone adds a new one. Validating
|
|
16
|
+
* once, where untrusted data enters, makes everything downstream trusted by
|
|
17
|
+
* construction — and it is a single line per operation that a reviewer can check.
|
|
18
|
+
*
|
|
19
|
+
* WHY REJECT RATHER THAN ESCAPE. Doubling quotes would let a malformed id through
|
|
20
|
+
* to a query that then returns nothing, or worse, something. A caller that sends a
|
|
21
|
+
* non-UUID where a UUID belongs has a bug, and the useful response is to say so.
|
|
22
|
+
* Silently returning the wrong rows is the failure mode worth designing against:
|
|
23
|
+
* an injected `' OR 1=1 --` in a customer filter widens a result set rather than
|
|
24
|
+
* breaking it, so it reads as working software while disclosing other people's data.
|
|
25
|
+
*
|
|
26
|
+
* @module @mj-biz-apps/orders-core-entities-server
|
|
27
|
+
*/
|
|
28
|
+
const UUID = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
|
|
29
|
+
/** Raised when caller-supplied input cannot safely reach a filter. */
|
|
30
|
+
export class InvalidOperationInputError extends Error {
|
|
31
|
+
constructor(message) {
|
|
32
|
+
super(message);
|
|
33
|
+
this.name = 'InvalidOperationInputError';
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Require a UUID, or throw.
|
|
38
|
+
*
|
|
39
|
+
* @param value The caller-supplied value.
|
|
40
|
+
* @param field Field name, used in the error so the caller can find their mistake.
|
|
41
|
+
* @returns The value, unchanged, once it is known to be a UUID.
|
|
42
|
+
* @throws {InvalidOperationInputError} If it is not a UUID.
|
|
43
|
+
*/
|
|
44
|
+
export function RequireUUID(value, field) {
|
|
45
|
+
if (typeof value !== 'string' || !UUID.test(value)) {
|
|
46
|
+
throw new InvalidOperationInputError(`${field} must be a UUID.`);
|
|
47
|
+
}
|
|
48
|
+
return value;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Require a UUID when present. Absent stays absent — many id inputs are optional
|
|
52
|
+
* filters, and an omitted filter is not an invalid one.
|
|
53
|
+
*/
|
|
54
|
+
export function RequireOptionalUUID(value, field) {
|
|
55
|
+
if (value === undefined || value === null || value === '')
|
|
56
|
+
return value;
|
|
57
|
+
RequireUUID(value, field);
|
|
58
|
+
return value;
|
|
59
|
+
}
|
|
60
|
+
/** Require every element of an id list to be a UUID. */
|
|
61
|
+
export function RequireUUIDs(values, field) {
|
|
62
|
+
if (!values?.length)
|
|
63
|
+
return [];
|
|
64
|
+
return values.map((v) => RequireUUID(v, field));
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Require an ISO date, returning just the `YYYY-MM-DD` portion.
|
|
68
|
+
*
|
|
69
|
+
* Dates are interpolated into comparisons, so they carry the same risk as ids.
|
|
70
|
+
* Truncating to the date part is deliberate: these filters compare days.
|
|
71
|
+
*/
|
|
72
|
+
export function RequireDate(value, field) {
|
|
73
|
+
// Validate the WHOLE string before truncating. Truncating first would accept
|
|
74
|
+
// `2026-03-04' OR '1'='1` by silently discarding the payload — safe by
|
|
75
|
+
// accident, and exactly the sanitise-don't-reject behaviour this module
|
|
76
|
+
// argues against: the caller never learns their input was wrong.
|
|
77
|
+
const whole = String(value);
|
|
78
|
+
const isDateOnly = /^\d{4}-\d{2}-\d{2}$/.test(whole);
|
|
79
|
+
const isDateTime = /^\d{4}-\d{2}-\d{2}[T ][\d:.]+(Z|[+-]\d{2}:?\d{2})?$/.test(whole);
|
|
80
|
+
if ((!isDateOnly && !isDateTime) || Number.isNaN(Date.parse(whole))) {
|
|
81
|
+
throw new InvalidOperationInputError(`${field} must be an ISO date (YYYY-MM-DD).`);
|
|
82
|
+
}
|
|
83
|
+
return whole.slice(0, 10);
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Escape a free-text value for a SQL string literal.
|
|
87
|
+
*
|
|
88
|
+
* For the values that are legitimately text rather than ids — a provider's refund
|
|
89
|
+
* reference, a search term. Doubling the quote is the SQL Server escape.
|
|
90
|
+
*/
|
|
91
|
+
export function EscapeText(value) {
|
|
92
|
+
return String(value).replace(/'/g, "''");
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* LOCAL FALLBACK for `EscapeSQLString` from `@memberjunction/global`.
|
|
96
|
+
*
|
|
97
|
+
* CLAUDE.md requires this function for SQL string escaping, but no published
|
|
98
|
+
* `@memberjunction/global` exports it — `6.1.0-edge.3` ships `Escape` and `EscapeHTML`
|
|
99
|
+
* and nothing else. Following the rule as written therefore broke the build. This keeps
|
|
100
|
+
* the rule followable at the call sites until MJ publishes the real one; delete it then
|
|
101
|
+
* and re-point `claimDriverHelpers.ts` and `GuestOrderClaimDriver.ts` at the package.
|
|
102
|
+
*
|
|
103
|
+
* Stricter than {@link EscapeText} on two counts, both of which CLAUDE.md calls out as
|
|
104
|
+
* the reasons to prefer `EscapeSQLString`: `null`/`undefined` become an empty string
|
|
105
|
+
* rather than the literal text `"null"`, and embedded null bytes are stripped — SQL
|
|
106
|
+
* Server truncates at `\0`, so a value carrying one can end a quoted literal early and
|
|
107
|
+
* leave the remainder of the input parsed as SQL.
|
|
108
|
+
*/
|
|
109
|
+
export function EscapeSQLString(value) {
|
|
110
|
+
if (value === null || value === undefined) {
|
|
111
|
+
return '';
|
|
112
|
+
}
|
|
113
|
+
return String(value).replace(/\0/g, '').replace(/'/g, "''");
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=sql-guards.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sql-guards.js","sourceRoot":"","sources":["../src/sql-guards.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,MAAM,IAAI,GAAG,+EAA+E,CAAC;AAE7F,sEAAsE;AACtE,MAAM,OAAO,0BAA2B,SAAQ,KAAK;IACjD,YAAY,OAAe;QACvB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,4BAA4B,CAAC;IAC7C,CAAC;CACJ;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,WAAW,CAAC,KAAa,EAAE,KAAa;IACpD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QACjD,MAAM,IAAI,0BAA0B,CAAC,GAAG,KAAK,kBAAkB,CAAC,CAAC;IACrE,CAAC;IACD,OAAO,KAAK,CAAC;AACjB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAsC,KAAQ,EAAE,KAAa;IAC5F,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,EAAE;QAAE,OAAO,KAAK,CAAC;IACxE,WAAW,CAAC,KAAe,EAAE,KAAK,CAAC,CAAC;IACpC,OAAO,KAAK,CAAC;AACjB,CAAC;AAED,wDAAwD;AACxD,MAAM,UAAU,YAAY,CAAC,MAAmC,EAAE,KAAa;IAC3E,IAAI,CAAC,MAAM,EAAE,MAAM;QAAE,OAAO,EAAE,CAAC;IAC/B,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;AACpD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CAAC,KAAa,EAAE,KAAa;IACpD,6EAA6E;IAC7E,uEAAuE;IACvE,wEAAwE;IACxE,iEAAiE;IACjE,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAC5B,MAAM,UAAU,GAAG,qBAAqB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACrD,MAAM,UAAU,GAAG,qDAAqD,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACrF,IAAI,CAAC,CAAC,UAAU,IAAI,CAAC,UAAU,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;QAClE,MAAM,IAAI,0BAA0B,CAAC,GAAG,KAAK,oCAAoC,CAAC,CAAC;IACvF,CAAC;IACD,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAC9B,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,UAAU,CAAC,KAAa;IACpC,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AAC7C,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,eAAe,CAAC,KAAgC;IAC5D,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxC,OAAO,EAAE,CAAC;IACd,CAAC;IACD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AAChE,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,8 +1,53 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mj-biz-apps/orders-core-entities-server",
|
|
3
|
-
"
|
|
4
|
-
"
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "5.2.0",
|
|
5
|
+
"description": "Server-side entity subclasses for BizApps Orders — order booking (one JE per line), line computation, and lifecycle hooks.",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"publishConfig": {
|
|
9
|
+
"access": "public"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"/dist"
|
|
13
|
+
],
|
|
14
|
+
"author": "MemberJunction.com",
|
|
5
15
|
"license": "BUSL-1.1",
|
|
6
|
-
"
|
|
7
|
-
|
|
8
|
-
|
|
16
|
+
"devDependencies": {
|
|
17
|
+
"@mj-biz-apps/accounting-core-entities-server": ">=0.1.0",
|
|
18
|
+
"@mj-biz-apps/accounting-engine-base": ">=0.1.0",
|
|
19
|
+
"@mj-biz-apps/tasks-entities": "1.2.3",
|
|
20
|
+
"typescript": "^5.9.3",
|
|
21
|
+
"vite": "^7.1.5",
|
|
22
|
+
"vitest": "^4.0.18"
|
|
23
|
+
},
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"@mj-biz-apps/orders-entities": "5.2.0"
|
|
26
|
+
},
|
|
27
|
+
"peerDependencies": {
|
|
28
|
+
"@memberjunction/communication-engine": "^6.1.0-edge.4",
|
|
29
|
+
"@memberjunction/communication-types": "^6.1.0-edge.4",
|
|
30
|
+
"@memberjunction/core": "^6.1.0-edge.4",
|
|
31
|
+
"@memberjunction/core-entities": "^6.1.0-edge.4",
|
|
32
|
+
"@memberjunction/core-entities-server": "^6.1.0-edge.4",
|
|
33
|
+
"@memberjunction/global": "^6.1.0-edge.4",
|
|
34
|
+
"@memberjunction/sqlserver-dataprovider": "^6.1.0-edge.4",
|
|
35
|
+
"@mj-biz-apps/accounting-core-entities-server": ">=0.1.0",
|
|
36
|
+
"@mj-biz-apps/accounting-engine-base": ">=0.1.0",
|
|
37
|
+
"@mj-biz-apps/tasks-entities": "^1.2.3"
|
|
38
|
+
},
|
|
39
|
+
"peerDependenciesMeta": {
|
|
40
|
+
"@mj-biz-apps/tasks-entities": {
|
|
41
|
+
"optional": true
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
"repository": {
|
|
45
|
+
"type": "git",
|
|
46
|
+
"url": "https://github.com/MemberJunction/bizapps-orders"
|
|
47
|
+
},
|
|
48
|
+
"scripts": {
|
|
49
|
+
"build": "tsc && tsc-alias -f",
|
|
50
|
+
"test": "vitest run",
|
|
51
|
+
"test:watch": "vitest"
|
|
52
|
+
}
|
|
53
|
+
}
|