solid-objects 1.0.0 → 1.0.2
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/CHANGELOG.md +22 -0
- package/README.md +1 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/docs/agents.md +12 -1
- package/docs/compare/dbos.md +391 -0
- package/docs/compare/graphile-worker.md +296 -0
- package/docs/compare/restate.md +290 -0
- package/docs/compare/rivetkit.md +282 -0
- package/docs/comparisons.md +17 -1
- package/examples/compare/agent-runtime.ts +46 -0
- package/examples/compare/agent-session.ts +50 -0
- package/examples/compare/cart-runtime.ts +80 -0
- package/examples/compare/chat-room.ts +84 -0
- package/examples/compare/chat-runtime.ts +38 -0
- package/examples/compare/shopping-cart.ts +100 -0
- package/package.json +1 -1
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { Actor, type EffectFailurePayload, type EffectSuccessPayload } from "solid-objects"
|
|
2
|
+
|
|
3
|
+
export const IDLE_MILLISECONDS = 30 * 60 * 1000
|
|
4
|
+
|
|
5
|
+
type ChargeArguments = { cartId: string; amountCents: number }
|
|
6
|
+
type ChargeResult = { status: "paid"; paymentId: string } | { status: "declined" }
|
|
7
|
+
type CheckArguments = { paymentKey: string }
|
|
8
|
+
type CheckResult = { status: "paid"; paymentId: string } | { status: "not_found" }
|
|
9
|
+
|
|
10
|
+
export class ShoppingCart extends Actor {
|
|
11
|
+
static override readonly actorType = "ShoppingCart"
|
|
12
|
+
|
|
13
|
+
items: Record<string, number> = {}
|
|
14
|
+
couponCode: string | null = null
|
|
15
|
+
status: "open" | "paying" | "checking" | "paid" | "released" = "open"
|
|
16
|
+
paymentId: string | null = null
|
|
17
|
+
activity = 0
|
|
18
|
+
|
|
19
|
+
addItem({ productId, quantity }: { productId: string; quantity: number }): {
|
|
20
|
+
items: Record<string, number>
|
|
21
|
+
} {
|
|
22
|
+
this.#requireOpen()
|
|
23
|
+
this.items = { ...this.items, [productId]: (this.items[productId] ?? 0) + quantity }
|
|
24
|
+
this.#armIdleRelease()
|
|
25
|
+
return { items: this.items }
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
applyCoupon({ code }: { code: string }): void {
|
|
29
|
+
this.#requireOpen()
|
|
30
|
+
this.couponCode = code
|
|
31
|
+
this.#armIdleRelease()
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
checkOut({ amountCents }: { amountCents: number }): { status: string } {
|
|
35
|
+
if (this.status === "paying" || this.status === "checking" || this.status === "paid") {
|
|
36
|
+
return { status: this.status }
|
|
37
|
+
}
|
|
38
|
+
this.#requireOpen()
|
|
39
|
+
this.status = "paying"
|
|
40
|
+
this.emit("charge_payment", {
|
|
41
|
+
arguments: { cartId: this.actorId, amountCents },
|
|
42
|
+
onSuccess: "paymentSettled",
|
|
43
|
+
onFailure: "paymentUnknown",
|
|
44
|
+
})
|
|
45
|
+
return { status: this.status }
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
paymentSettled({ result }: EffectSuccessPayload<ChargeArguments, ChargeResult>): void {
|
|
49
|
+
if (result.status === "paid") {
|
|
50
|
+
this.#markPaid(result.paymentId)
|
|
51
|
+
return
|
|
52
|
+
}
|
|
53
|
+
this.#reopen()
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
paymentUnknown({ effectId }: EffectFailurePayload<ChargeArguments>): void {
|
|
57
|
+
this.status = "checking"
|
|
58
|
+
this.emit("check_payment", {
|
|
59
|
+
arguments: { paymentKey: effectId },
|
|
60
|
+
onSuccess: "paymentChecked",
|
|
61
|
+
})
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
paymentChecked({ result }: EffectSuccessPayload<CheckArguments, CheckResult>): void {
|
|
65
|
+
if (result.status === "paid") {
|
|
66
|
+
this.#markPaid(result.paymentId)
|
|
67
|
+
return
|
|
68
|
+
}
|
|
69
|
+
this.#reopen()
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
releaseIfIdle({ activity }: { activity: number }): void {
|
|
73
|
+
if (activity !== this.activity || this.status !== "open") return
|
|
74
|
+
this.status = "released"
|
|
75
|
+
this.emit("release_stock", { arguments: { cartId: this.actorId, items: this.items } })
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
#markPaid(paymentId: string): void {
|
|
79
|
+
this.status = "paid"
|
|
80
|
+
this.paymentId = paymentId
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
#reopen(): void {
|
|
84
|
+
this.status = "open"
|
|
85
|
+
this.#armIdleRelease()
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
#requireOpen(): void {
|
|
89
|
+
if (this.status !== "open") {
|
|
90
|
+
this.reject("cart_closed", { message: `The cart is ${this.status}` })
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
#armIdleRelease(): void {
|
|
95
|
+
this.activity += 1
|
|
96
|
+
this.schedule({ at: new Date(Date.now() + IDLE_MILLISECONDS) }).releaseIfIdle({
|
|
97
|
+
activity: this.activity,
|
|
98
|
+
})
|
|
99
|
+
}
|
|
100
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "solid-objects",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "Fix race conditions across Node.js processes: ordered operations, expiring holds, and state that survives a restart, in your SQL database. A SQL-backed virtual actor library for TypeScript and Node.js.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|