@stamprally/core 0.8.0 → 0.10.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/README.md +10 -143
- package/dist/index.cjs +687 -1274
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +280 -670
- package/dist/index.d.ts +280 -670
- package/dist/index.js +677 -1263
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,160 +1,27 @@
|
|
|
1
1
|
# @stamprally/core
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
The package contains the domain model, immutable state transitions, progress
|
|
5
|
-
calculation, persistence adapters, and browser sensor detectors.
|
|
6
|
-
|
|
7
|
-
## Install
|
|
8
|
-
|
|
9
|
-
```sh
|
|
10
|
-
npm install @stamprally/core
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
Or with pnpm:
|
|
14
|
-
|
|
15
|
-
```sh
|
|
16
|
-
pnpm add @stamprally/core
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
## Quick start
|
|
3
|
+
Dependency-free domain models, immutable state transitions, storage adapters, browser detectors, and safe configuration parsers.
|
|
20
4
|
|
|
21
5
|
```ts
|
|
22
|
-
import {
|
|
23
|
-
InMemoryStorage,
|
|
24
|
-
StampRallyClient,
|
|
25
|
-
type RallyConfig,
|
|
26
|
-
} from "@stamprally/core";
|
|
6
|
+
import { InMemoryStorage, StampRallyClient, type PublicRallyConfig } from "@stamprally/core";
|
|
27
7
|
|
|
28
|
-
const config:
|
|
8
|
+
const config: PublicRallyConfig = {
|
|
29
9
|
id: "city-tour",
|
|
10
|
+
version: "0.9.1",
|
|
30
11
|
title: "City Tour",
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
id: "station",
|
|
34
|
-
name: "Central Station",
|
|
35
|
-
condition: { type: "token", token: "ARRIVED" },
|
|
36
|
-
},
|
|
37
|
-
],
|
|
12
|
+
spots: [{ id: "station", orderIndex: 0, name: "Central Station", conditions: [{ type: "passcode" }] }],
|
|
13
|
+
rewards: [],
|
|
38
14
|
};
|
|
39
|
-
|
|
40
15
|
const client = new StampRallyClient(config, new InMemoryStorage());
|
|
41
16
|
await client.init();
|
|
42
|
-
|
|
43
|
-
const result = await client.acquire(
|
|
44
|
-
"station",
|
|
45
|
-
{ type: "token", token: "ARRIVED" },
|
|
46
|
-
);
|
|
47
|
-
|
|
48
|
-
if (result.ok) {
|
|
49
|
-
console.log(result.value.nextState.records);
|
|
50
|
-
} else {
|
|
51
|
-
console.error(result.error.code);
|
|
52
|
-
}
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
`StampRallyClient` serializes operations, persists successful state changes, and
|
|
56
|
-
notifies subscribers with immutable state snapshots. Call `client.reset()` to
|
|
57
|
-
clear the current rally, or `client.restore(state)` to replace it with a
|
|
58
|
-
validated state for the same rally.
|
|
59
|
-
|
|
60
|
-
## Conditions
|
|
61
|
-
|
|
62
|
-
Stamp conditions support instant acquisition, tokens, geofences, recursive
|
|
63
|
-
combinations, and time windows:
|
|
64
|
-
|
|
65
|
-
```ts
|
|
66
|
-
const config: RallyConfig = {
|
|
67
|
-
id: "museum-tour",
|
|
68
|
-
isSequential: true,
|
|
69
|
-
stamps: [
|
|
70
|
-
{ id: "entrance", name: "Entrance", condition: { type: "instant" } },
|
|
71
|
-
{
|
|
72
|
-
id: "gallery",
|
|
73
|
-
name: "Gallery",
|
|
74
|
-
condition: {
|
|
75
|
-
type: "time_window",
|
|
76
|
-
startsAt: "2026-04-01T09:00:00.000Z",
|
|
77
|
-
endsAt: "2026-04-01T18:00:00.000Z",
|
|
78
|
-
condition: { type: "geo", latitude: 35.6812, longitude: 139.7671, radiusMeters: 100 },
|
|
79
|
-
},
|
|
80
|
-
},
|
|
81
|
-
],
|
|
82
|
-
};
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
Use `calculateProgress(state, config)` to obtain the completion percentage,
|
|
86
|
-
remaining stamps, and next available stamps. For lower-level integrations,
|
|
87
|
-
`evaluateCondition`, `processStamp`, and `consumeReward` are also exported.
|
|
88
|
-
|
|
89
|
-
## Storage
|
|
90
|
-
|
|
91
|
-
All storage implementations satisfy the `StampStorage` interface:
|
|
92
|
-
|
|
93
|
-
- `InMemoryStorage` for tests, server-side rendering, or short-lived sessions.
|
|
94
|
-
- `LocalStorageAdapter` for browser LocalStorage persistence.
|
|
95
|
-
- `IndexedDBAdapter` for browser IndexedDB persistence.
|
|
96
|
-
|
|
97
|
-
```ts
|
|
98
|
-
import { LocalStorageAdapter, StampRallyClient } from "@stamprally/core";
|
|
99
|
-
|
|
100
|
-
const storage = new LocalStorageAdapter({
|
|
101
|
-
keyPrefix: "my-app:",
|
|
102
|
-
failureMode: "throw",
|
|
103
|
-
});
|
|
104
|
-
const client = new StampRallyClient(config, storage);
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
`LocalStorageAdapter` uses an instance-local in-memory fallback by default when
|
|
108
|
-
storage is unavailable, blocked, corrupt, or full. Use `failureMode: "throw"`
|
|
109
|
-
when the application must handle a typed `StorageAdapterError` instead.
|
|
110
|
-
|
|
111
|
-
Progress can also be exported and imported as a rally-scoped recovery token with
|
|
112
|
-
`exportProgressToken` and `importProgressToken`.
|
|
113
|
-
|
|
114
|
-
## Browser detectors
|
|
115
|
-
|
|
116
|
-
The optional detectors convert browser sensor output into a typed
|
|
117
|
-
`VerificationContext` and return a `Result` instead of throwing for unsupported
|
|
118
|
-
environments, permission failures, timeouts, and device errors.
|
|
119
|
-
|
|
120
|
-
```ts
|
|
121
|
-
import {
|
|
122
|
-
getCurrentGeoContext,
|
|
123
|
-
isGeolocationSupported,
|
|
124
|
-
isNfcSupported,
|
|
125
|
-
isQrSupported,
|
|
126
|
-
readNfcContext,
|
|
127
|
-
readQrContext,
|
|
128
|
-
} from "@stamprally/core";
|
|
129
|
-
|
|
130
|
-
if (isGeolocationSupported()) {
|
|
131
|
-
const result = await getCurrentGeoContext({ enableHighAccuracy: true });
|
|
132
|
-
if (result.ok) {
|
|
133
|
-
await client.acquire("gallery", result.value);
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
if (isNfcSupported()) {
|
|
138
|
-
const result = await readNfcContext();
|
|
139
|
-
if (result.ok) await client.acquire("entrance", result.value);
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
if (isQrSupported()) {
|
|
143
|
-
const result = await readQrContext(videoElement, { facingMode: "environment" });
|
|
144
|
-
if (result.ok) await client.acquire("entrance", result.value);
|
|
145
|
-
}
|
|
17
|
+
const result = await client.checkIn("station", "ARRIVED");
|
|
146
18
|
```
|
|
147
19
|
|
|
148
|
-
|
|
149
|
-
permission. Web NFC and `BarcodeDetector` are not available in every browser,
|
|
150
|
-
so applications should keep a manual-input fallback.
|
|
20
|
+
Use `toPublicConfig(adminConfig)` to remove QR tokens, passcodes, NFC identifiers, custom secret parameters, staff credentials, and gated digital content before sending configuration to a browser. Use `safeParseAdminConfig` and `safeParsePublicConfig` at JSON boundaries; failures include paths such as `spots[0].conditions[1].latitude`.
|
|
151
21
|
|
|
152
|
-
|
|
22
|
+
The browser detectors `getCurrentGeoContext`, `readNfcContext`, and `readQrContext` return typed results and do not throw for unsupported environments, denied permissions, timeouts, or device errors. Keep manual fallbacks for browsers without Web NFC or `BarcodeDetector`.
|
|
153
23
|
|
|
154
|
-
|
|
155
|
-
implementation. State transitions never mutate their input. Verification inputs
|
|
156
|
-
such as tokens and coordinates are not copied into stamp record metadata by the
|
|
157
|
-
engine.
|
|
24
|
+
`InMemoryStorage`, `LocalStorageAdapter`, and `IndexedDBAdapter` implement `StampStorage`. `updateLocalizedField` updates one locale without dropping existing translations.
|
|
158
25
|
|
|
159
26
|
## License
|
|
160
27
|
|