@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 CHANGED
@@ -1,160 +1,27 @@
1
1
  # @stamprally/core
2
2
 
3
- Headless, storage-agnostic stamp rally engine for TypeScript and JavaScript.
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: RallyConfig = {
8
+ const config: PublicRallyConfig = {
29
9
  id: "city-tour",
10
+ version: "0.9.1",
30
11
  title: "City Tour",
31
- stamps: [
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
- Geolocation, Web NFC, and camera access require a secure context and user
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
- ## Privacy and immutability
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
- The domain engine does not depend on the DOM, React, or a specific persistence
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