@ontrails/store 0.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/CHANGELOG.md ADDED
@@ -0,0 +1,329 @@
1
+ # @ontrails/store
2
+
3
+ ## 0.2.0
4
+
5
+ ### Patch Changes
6
+
7
+ - [`664e8bb`](https://github.com/outfitter-dev/trails/commit/664e8bb049e61f1d47cec1dd246606707af5d1a8): Point public installation examples at exact approved 0.2.0 versions and distinguish the prepared source release from pending npm publication.
8
+ - [`b3ddf91`](https://github.com/outfitter-dev/trails/commit/b3ddf918ada8211f44983512e2bbdfbc5b66d722): Prepare the first normal Trails release at `0.2.0` on `latest`, replacing the unpublished 1.0.0 source release. The target advances the original `0.1.0` source minor, which was never published under the current package names. Public packages remain in lockstep. Update consumer installation guidance and provide a temporary manifest bridge for old 1.0 beta sources. Published beta versions remain unchanged; minor 0.x releases may carry documented breaking changes.
9
+
10
+ The `1.0.0` section retained below records an unpublished preparation, not an npm release. Its accumulated changes are included in `0.2.0`; the section remains as source history alongside the published beta entries.
11
+
12
+ ## 1.0.0
13
+
14
+ ### Major Changes
15
+
16
+ - [`3395234`](https://github.com/outfitter-dev/trails/commit/33952349f2d475b170376a63587c89e50be3247a): Move store adapter-binding helpers to `@ontrails/store/adapter-support` and topographer direct database/admin helpers to `@ontrails/topographer/backend-support`, keeping root exports focused on contract-level APIs.
17
+ - [`6300f70`](https://github.com/outfitter-dev/trails/commit/6300f709bb6dffc0e6cc82479fe8d0204c52bbba): BREAKING: rename the shared store backend option type from `StoreConnectorOptions` to `StoreAdapterOptions`.
18
+
19
+ ### Minor Changes
20
+
21
+ - [`69057e9`](https://github.com/outfitter-dev/trails/commit/69057e9348006b2b70c9f6237572a5aa8de3ee1f): Add hierarchical CLI command trees and structured input, enforce established-only topo exports across surfaces, move developer topo and tracing state onto shared `trails.db` with pins and maintenance flows, and ship schema-derived stores through `@ontrails/store` and its Drizzle runtime.
22
+ - [`5adb995`](https://github.com/outfitter-dev/trails/commit/5adb99551c2dda6190d46cce7f60bb08d63c99aa): Complete the v1 hard cutover from the authored `blaze` field to
23
+ `implementation` across trail contracts, surface projections, tests, examples,
24
+ and public source-analysis helpers. Existing applications must rename authored
25
+ trail behavior fields and direct trail-object access before upgrading.
26
+ - [`88a6a62`](https://github.com/outfitter-dev/trails/commit/88a6a62a9e9e230ca6d368fa78dc3ece6c816204): Complete the v1 classification-first cutover from projection/project vocabulary
27
+ to derive/derived for contract-owned fact production and render/rendered for
28
+ surface presentation. Public type, helper, rule, relation, and report names move
29
+ without compatibility aliases; ordinary repository/project nouns remain
30
+ explicit preserves or structured review inventory.
31
+ - [`6712075`](https://github.com/outfitter-dev/trails/commit/67120754df3f614c7f4dd98be1fa0ba9d69b7765): Complete the v1 hard cutover from the `contour` domain-object declaration
32
+ vocabulary to `entity` across contracts, topo facts, store helpers, Warden,
33
+ Wayfinder, operator surfaces, examples, and generated locks. Existing
34
+ applications must rename contour APIs, run `trails dev reset --yes` to discard
35
+ pre-cutover local Topographer snapshots, and then recompile committed
36
+ `trails.lock` artifacts before upgrading. Those derived snapshots are
37
+ intentionally not read through a compatibility layer.
38
+ The entity-shaped wire contract advances `TopoGraph` and split lock manifests
39
+ from schema version 3 to 4; old split artifacts fail with regeneration guidance,
40
+ while the canonical root `trails.lock` remains schema version 5.
41
+ Wayfinder reports those stale rows as topo-store drift while keeping current
42
+ committed lock facts available for inspection.
43
+
44
+ ### Patch Changes
45
+
46
+ - [`e41c382`](https://github.com/outfitter-dev/trails/commit/e41c3829c2d692683b78c730e67fd5b17ac0ff4e): Document beta-channel install guidance in package and adapter README install snippets so consumers use explicit `@beta` (or pinned `1.0.0-beta.N`) tags instead of accidental `latest` resolution during the prerelease line. Adds the policy doc at `docs/releases/beta-channel-policy.md`, prints both `latest` and `beta` dist-tags in `bun run publish:registry-check`, and aligns plugin/skill install snippets.
47
+ - [`9874e0b`](https://github.com/outfitter-dev/trails/commit/9874e0bb034c0f98edeb19833d9d3519c2a07a4c): Add `@ontrails/cloudflare/d1`, an env-bound Cloudflare D1 store resource for `@ontrails/store` definitions. The new subpath exports `cloudflareD1` and `connectD1`, supports the backend-agnostic store accessor contract (`get`, `list`, `upsert`, `remove`), versioned-table optimistic concurrency, fixture/mock seeding, store-derived write signals, Miniflare-backed conformance tests, and Worker env-bridge integration.
48
+
49
+ `@ontrails/core` and `@ontrails/store` no longer require the Bun global for signal fire ids or late-bound store signal tokens, so store definitions and store-derived signal emission work inside Worker modules. `@ontrails/warden` now treats `cloudflareD1` as a required Cloudflare public export with `@example` coverage.
50
+
51
+ - [`e898cc4`](https://github.com/outfitter-dev/trails/commit/e898cc4042ffa66f977b425a98419ee77183f27d): Add repo-level Knip dead-code detection and remove stale internal exports and unused package dependencies surfaced by the new check.
52
+ - [`851a2a3`](https://github.com/outfitter-dev/trails/commit/851a2a3cb805993d16ef74d43d3c963f286cce15): Derive trail caller and blaze input types from the authored input schema while keeping one public input contract.
53
+ - [`f7ec225`](https://github.com/outfitter-dev/trails/commit/f7ec225c01482f8fb55afd174add3d961a63171b): `sync()` gains the factory-contract options `crud()` and `reconcile()` received in TRL-1195: a `permit` option declared on the produced trail, and per-endpoint `contour` options on `SyncEndpoint` so a `crud()` bundle's table contour can be shared instead of colliding as a duplicate registration at `topo()`.
54
+ - [`49c2e7d`](https://github.com/outfitter-dev/trails/commit/49c2e7d5c7c063b9aa6abee1d2932bf3003133cc): Refresh published package README taxonomy to use adapter language instead of retired connector vocabulary.
55
+ - [`5a38c73`](https://github.com/outfitter-dev/trails/commit/5a38c73092f81612769be4b44944d828c3436e07): Complete the store factory trail contracts (TRL-1195, absorbing TRL-1177 and TRL-1178). `crud()` gains `permit` (applied to every produced trail) and `permits` (per-operation overrides, so destroy trails satisfy permit governance) plus a `contour` option, and the returned tuple now exposes the table contour it registered as a `contour` property. `reconcile()` gains `permit` and accepts a shared `contour` instance, so crud + reconcile on one table register cleanly in a single `topo()` instead of colliding on a duplicate contour name. `TableContour` is exported from `@ontrails/store/trails`. Consuming apps no longer need to post-process factory trails to attach permits or strip contours.
56
+ - [`b1fbe57`](https://github.com/outfitter-dev/trails/commit/b1fbe574e6f44d1fecb5e3a000270955c0a77b7b): Publish Bun-validated package tarballs through an npm trusted-publishing adapter
57
+ binding, add exact repository metadata for each public workspace package, and
58
+ correct the native Bun release descriptor to its pack-only runtime boundary.
59
+ - [`ab1c77c`](https://github.com/outfitter-dev/trails/commit/ab1c77cddd90c30af28887f2bbd2cf2416900068): Advertise first-party adapter target metadata for catalog derivation.
60
+ - [`9bf592d`](https://github.com/outfitter-dev/trails/commit/9bf592ddba46aa12e3f4e6ffc0f772f7a41ed3df): Declare verified first-party adapter metadata for Drizzle, HTTP/Bun, and Store/Jsonfile so shared adapter checks can dogfood real owner targets.
61
+ - [`df9a7d0`](https://github.com/outfitter-dev/trails/commit/df9a7d00fe4d9ebec948b6ebed6dc4525fc8e0dc): Add project-aware public export-map governance for @ontrails workspace docs,
62
+ imports, root barrels, and bin-only package surfaces.
63
+
64
+ ## 1.0.0-beta.50
65
+
66
+ ## 1.0.0-beta.49
67
+
68
+ ## 1.0.0-beta.48
69
+
70
+ ## 1.0.0-beta.47
71
+
72
+ ## 1.0.0-beta.46
73
+
74
+ ## 1.0.0-beta.45
75
+
76
+ ## 1.0.0-beta.44
77
+
78
+ ### Patch Changes
79
+
80
+ - [`b1fbe57`](https://github.com/outfitter-dev/trails/commit/b1fbe574e6f44d1fecb5e3a000270955c0a77b7b): Publish Bun-validated package tarballs through an npm trusted-publishing adapter
81
+ binding, add exact repository metadata for each public workspace package, and
82
+ correct the native Bun release descriptor to its pack-only runtime boundary.
83
+
84
+ ## 1.0.0-beta.43
85
+
86
+ ### Minor Changes
87
+
88
+ - [`88a6a62`](https://github.com/outfitter-dev/trails/commit/88a6a62a9e9e230ca6d368fa78dc3ece6c816204): Complete the v1 classification-first cutover from projection/project vocabulary
89
+ to derive/derived for contract-owned fact production and render/rendered for
90
+ surface presentation. Public type, helper, rule, relation, and report names move
91
+ without compatibility aliases; ordinary repository/project nouns remain
92
+ explicit preserves or structured review inventory.
93
+
94
+ ## 1.0.0-beta.42
95
+
96
+ ## 1.0.0-beta.41
97
+
98
+ ## 1.0.0-beta.40
99
+
100
+ ### Minor Changes
101
+
102
+ - [`5adb995`](https://github.com/outfitter-dev/trails/commit/5adb99551c2dda6190d46cce7f60bb08d63c99aa): Complete the v1 hard cutover from the authored `blaze` field to
103
+ `implementation` across trail contracts, surface projections, tests, examples,
104
+ and public source-analysis helpers. Existing applications must rename authored
105
+ trail behavior fields and direct trail-object access before upgrading.
106
+ - [`6712075`](https://github.com/outfitter-dev/trails/commit/67120754df3f614c7f4dd98be1fa0ba9d69b7765): Complete the v1 hard cutover from the `contour` domain-object declaration
107
+ vocabulary to `entity` across contracts, topo facts, store helpers, Warden,
108
+ Wayfinder, operator surfaces, examples, and generated locks. Existing
109
+ applications must rename contour APIs, run `trails dev reset --yes` to discard
110
+ pre-cutover local Topographer snapshots, and then recompile committed
111
+ `trails.lock` artifacts before upgrading. Those derived snapshots are
112
+ intentionally not read through a compatibility layer.
113
+ The entity-shaped wire contract advances `TopoGraph` and split lock manifests
114
+ from schema version 3 to 4; old split artifacts fail with regeneration guidance,
115
+ while the canonical root `trails.lock` remains schema version 5.
116
+ Wayfinder reports those stale rows as topo-store drift while keeping current
117
+ committed lock facts available for inspection.
118
+
119
+ ### Patch Changes
120
+
121
+ - [`9874e0b`](https://github.com/outfitter-dev/trails/commit/9874e0bb034c0f98edeb19833d9d3519c2a07a4c): Add `@ontrails/cloudflare/d1`, an env-bound Cloudflare D1 store resource for `@ontrails/store` definitions. The new subpath exports `cloudflareD1` and `connectD1`, supports the backend-agnostic store accessor contract (`get`, `list`, `upsert`, `remove`), versioned-table optimistic concurrency, fixture/mock seeding, store-derived write signals, Miniflare-backed conformance tests, and Worker env-bridge integration.
122
+
123
+ `@ontrails/core` and `@ontrails/store` no longer require the Bun global for signal fire ids or late-bound store signal tokens, so store definitions and store-derived signal emission work inside Worker modules. `@ontrails/warden` now treats `cloudflareD1` as a required Cloudflare public export with `@example` coverage.
124
+
125
+ - [`9bf592d`](https://github.com/outfitter-dev/trails/commit/9bf592ddba46aa12e3f4e6ffc0f772f7a41ed3df): Declare verified first-party adapter metadata for Drizzle, HTTP/Bun, and Store/Jsonfile so shared adapter checks can dogfood real owner targets.
126
+
127
+ ## 1.0.0-beta.39
128
+
129
+ ### Patch Changes
130
+
131
+ - [`f7ec225`](https://github.com/outfitter-dev/trails/commit/f7ec225c01482f8fb55afd174add3d961a63171b): `sync()` gains the factory-contract options `crud()` and `reconcile()` received in TRL-1195: a `permit` option declared on the produced trail, and per-endpoint `contour` options on `SyncEndpoint` so a `crud()` bundle's table contour can be shared instead of colliding as a duplicate registration at `topo()`.
132
+ - [`5a38c73`](https://github.com/outfitter-dev/trails/commit/5a38c73092f81612769be4b44944d828c3436e07): Complete the store factory trail contracts (TRL-1195, absorbing TRL-1177 and TRL-1178). `crud()` gains `permit` (applied to every produced trail) and `permits` (per-operation overrides, so destroy trails satisfy permit governance) plus a `contour` option, and the returned tuple now exposes the table contour it registered as a `contour` property. `reconcile()` gains `permit` and accepts a shared `contour` instance, so crud + reconcile on one table register cleanly in a single `topo()` instead of colliding on a duplicate contour name. `TableContour` is exported from `@ontrails/store/trails`. Consuming apps no longer need to post-process factory trails to attach permits or strip contours.
133
+
134
+ ## 1.0.0-beta.38
135
+
136
+ ## 1.0.0-beta.37
137
+
138
+ ## 1.0.0-beta.36
139
+
140
+ ## 1.0.0-beta.35
141
+
142
+ ## 1.0.0-beta.34
143
+
144
+ ## 1.0.0-beta.33
145
+
146
+ ## 1.0.0-beta.32
147
+
148
+ ### Patch Changes
149
+
150
+ - Updated dependencies [3e5c0fc]
151
+ - Updated dependencies [f3c4fef]
152
+ - Updated dependencies [cb0a9d8]
153
+ - Updated dependencies [21c6dda]
154
+ - Updated dependencies [fe72b84]
155
+ - @ontrails/core@1.0.0-beta.32
156
+
157
+ ## 1.0.0-beta.31
158
+
159
+ ### Patch Changes
160
+
161
+ - Updated dependencies [4cd5d4e]
162
+ - Updated dependencies [38907cc]
163
+ - @ontrails/core@1.0.0-beta.31
164
+
165
+ ## 1.0.0-beta.30
166
+
167
+ ### Patch Changes
168
+
169
+ - @ontrails/core@1.0.0-beta.30
170
+
171
+ ## 1.0.0-beta.29
172
+
173
+ ### Patch Changes
174
+
175
+ - @ontrails/core@1.0.0-beta.29
176
+
177
+ ## 1.0.0-beta.28
178
+
179
+ ### Patch Changes
180
+
181
+ - @ontrails/core@1.0.0-beta.28
182
+
183
+ ## 1.0.0-beta.27
184
+
185
+ ### Patch Changes
186
+
187
+ - @ontrails/core@1.0.0-beta.27
188
+
189
+ ## 1.0.0-beta.26
190
+
191
+ ### Patch Changes
192
+
193
+ - Updated dependencies [1307568]
194
+ - Updated dependencies [371d19e]
195
+ - @ontrails/core@1.0.0-beta.26
196
+
197
+ ## 1.0.0-beta.25
198
+
199
+ ### Patch Changes
200
+
201
+ - Updated dependencies [c36aca9]
202
+ - Updated dependencies [3befcf1]
203
+ - Updated dependencies [a4f9cf6]
204
+ - Updated dependencies [9bcf34e]
205
+ - @ontrails/core@1.0.0-beta.25
206
+
207
+ ## 1.0.0-beta.24
208
+
209
+ ### Patch Changes
210
+
211
+ - @ontrails/core@1.0.0-beta.24
212
+
213
+ ## 1.0.0-beta.23
214
+
215
+ ### Patch Changes
216
+
217
+ - @ontrails/core@1.0.0-beta.23
218
+
219
+ ## 1.0.0-beta.22
220
+
221
+ ### Patch Changes
222
+
223
+ - @ontrails/core@1.0.0-beta.22
224
+
225
+ ## 1.0.0-beta.21
226
+
227
+ ### Patch Changes
228
+
229
+ - Updated dependencies [99523f2]
230
+ - @ontrails/core@1.0.0-beta.21
231
+
232
+ ## 1.0.0-beta.20
233
+
234
+ ### Patch Changes
235
+
236
+ - 851a2a3: Derive trail caller and blaze input types from the authored input schema while keeping one public input contract.
237
+ - Updated dependencies [851a2a3]
238
+ - @ontrails/core@1.0.0-beta.20
239
+
240
+ ## 1.0.0-beta.19
241
+
242
+ ### Patch Changes
243
+
244
+ - e41c382: Document beta-channel install guidance in package and adapter README install snippets so consumers use explicit `@beta` (or pinned `1.0.0-beta.N`) tags instead of accidental `latest` resolution during the prerelease line. Adds the policy doc at `docs/releases/beta-channel-policy.md`, prints both `latest` and `beta` dist-tags in `bun run publish:registry-check`, and aligns plugin/skill install snippets.
245
+ - ab1c77c: Advertise first-party adapter target metadata for catalog derivation.
246
+ - Updated dependencies [e41c382]
247
+ - Updated dependencies [1eb5bdc]
248
+ - Updated dependencies [f8d80b9]
249
+ - Updated dependencies [846a597]
250
+ - Updated dependencies [223aaad]
251
+ - Updated dependencies [3125f4d]
252
+ - Updated dependencies [2494dc6]
253
+ - Updated dependencies [2d53717]
254
+ - Updated dependencies [16cb740]
255
+ - Updated dependencies [8894ecb]
256
+ - Updated dependencies [fdf7ec9]
257
+ - Updated dependencies [d76be13]
258
+ - Updated dependencies [84f56a5]
259
+ - Updated dependencies [431b04c]
260
+ - Updated dependencies [5d88104]
261
+ - Updated dependencies [f04a9ef]
262
+ - @ontrails/core@1.0.0-beta.19
263
+
264
+ ## 1.0.0-beta.18
265
+
266
+ ### Patch Changes
267
+
268
+ - @ontrails/core@1.0.0-beta.18
269
+
270
+ ## 1.0.0-beta.17
271
+
272
+ ### Patch Changes
273
+
274
+ - Updated dependencies [3dc8254]
275
+ - @ontrails/core@1.0.0-beta.17
276
+
277
+ ## 1.0.0-beta.16
278
+
279
+ ### Major Changes
280
+
281
+ - 3395234: Move store adapter-binding helpers to `@ontrails/store/adapter-support` and topographer direct database/admin helpers to `@ontrails/topographer/backend-support`, keeping root exports focused on contract-level APIs.
282
+ - 6300f70: BREAKING: rename the shared store backend option type from `StoreConnectorOptions` to `StoreAdapterOptions`.
283
+
284
+ ### Patch Changes
285
+
286
+ - e898cc4: Add repo-level Knip dead-code detection and remove stale internal exports and unused package dependencies surfaced by the new check.
287
+ - 49c2e7d: Refresh published package README taxonomy to use adapter language instead of retired connector vocabulary.
288
+ - df9a7d0: Add project-aware public export-map governance for @ontrails workspace docs,
289
+ imports, root barrels, and bin-only package surfaces.
290
+ - Updated dependencies [73622ae]
291
+ - Updated dependencies [6300f70]
292
+ - Updated dependencies [d172013]
293
+ - Updated dependencies [c3fc5c3]
294
+ - Updated dependencies [20d7a5c]
295
+ - Updated dependencies [be5fb46]
296
+ - Updated dependencies [e898cc4]
297
+ - Updated dependencies [3395234]
298
+ - Updated dependencies [bcdc484]
299
+ - Updated dependencies [331e3a9]
300
+ - Updated dependencies [4399fdb]
301
+ - Updated dependencies [4b8d13b]
302
+ - Updated dependencies [112b9f2]
303
+ - Updated dependencies [893025e]
304
+ - Updated dependencies [eec5e9d]
305
+ - Updated dependencies [ebd4434]
306
+ - Updated dependencies [863d473]
307
+ - Updated dependencies [344f2f7]
308
+ - Updated dependencies [26f9ffd]
309
+ - Updated dependencies [10eae9a]
310
+ - Updated dependencies [22c6c06]
311
+ - @ontrails/core@1.0.0-beta.16
312
+
313
+ ## 1.0.0-beta.15
314
+
315
+ ### Patch Changes
316
+
317
+ - Updated dependencies [4ad6b25]
318
+ - @ontrails/core@1.0.0-beta.15
319
+
320
+ ## 1.0.0-beta.14
321
+
322
+ ### Minor Changes
323
+
324
+ - 69057e9: Add hierarchical CLI command trees and structured input, enforce established-only topo exports across trailheads, move developer topo and tracker state onto shared `trails.db` with pins and maintenance flows, and ship schema-derived stores through `@ontrails/store` and its Drizzle runtime.
325
+
326
+ ### Patch Changes
327
+
328
+ - Updated dependencies [69057e9]
329
+ - @ontrails/core@1.0.0-beta.14
package/README.md ADDED
@@ -0,0 +1,290 @@
1
+ # @ontrails/store
2
+
3
+ Schema-derived persistence for Trails.
4
+
5
+ The root package owns the backend-agnostic `store(...)` declaration. External adapter packages such as `@ontrails/drizzle` bind that declaration to a concrete runtime, and first-party built-ins such as `@ontrails/store/jsonfile` live as opt-in subpaths on the same package.
6
+
7
+ ## The two layers
8
+
9
+ ### 1. Declare the store contract
10
+
11
+ ```typescript
12
+ import { store } from '@ontrails/store';
13
+
14
+ export const db = store({
15
+ gists: {
16
+ schema: gistSchema,
17
+ identity: 'id',
18
+ generated: ['id', 'createdAt', 'updatedAt'],
19
+ indexed: ['owner', 'createdAt'],
20
+ versioned: true,
21
+ },
22
+ files: {
23
+ schema: fileSchema,
24
+ identity: 'id',
25
+ generated: ['id'],
26
+ references: { gistId: 'gists' },
27
+ },
28
+ });
29
+ ```
30
+
31
+ This declaration is pure metadata:
32
+
33
+ - full entity schema
34
+ - insert schema
35
+ - update schema
36
+ - fixture schema
37
+ - derived change-signal handles (`table.signals.created|updated|removed`)
38
+ - identity field
39
+ - generated-field metadata
40
+ - optional framework-managed version tracking
41
+ - indexed markers
42
+ - references
43
+
44
+ No database connection is opened here. The returned value is the durable authored source of truth.
45
+
46
+ ### 2. Bind it to a concrete runtime
47
+
48
+ ```typescript
49
+ import { store } from '@ontrails/store';
50
+ import { connectDrizzle } from '@ontrails/drizzle';
51
+
52
+ const definition = store({
53
+ gists: {
54
+ schema: gistSchema,
55
+ identity: 'id',
56
+ generated: ['id', 'createdAt', 'updatedAt'],
57
+ },
58
+ });
59
+
60
+ export const db = connectDrizzle(definition, {
61
+ id: 'db.main',
62
+ url: ':memory:',
63
+ });
64
+ ```
65
+
66
+ The bound store is a resource. Use it directly in trails:
67
+
68
+ ```typescript
69
+ export const list = trail('gist.list', {
70
+ resources: [db],
71
+ intent: 'read',
72
+ implementation: async (_input, ctx) => {
73
+ const conn = db.from(ctx);
74
+ const gists = await conn.gists.list();
75
+ return Result.ok(gists);
76
+ },
77
+ });
78
+ ```
79
+
80
+ ### Built-in local backend
81
+
82
+ For a zero-extra-package local backend, use the first-party JSON file binding:
83
+
84
+ ```typescript
85
+ import { store } from '@ontrails/store';
86
+ import { jsonFile } from '@ontrails/store/jsonfile';
87
+
88
+ const definition = store({
89
+ gists: {
90
+ schema: gistSchema,
91
+ identity: 'id',
92
+ generated: ['id', 'createdAt', 'updatedAt'],
93
+ },
94
+ });
95
+
96
+ export const db = jsonFile(definition, {
97
+ dir: './data',
98
+ });
99
+ ```
100
+
101
+ ## Typed accessors
102
+
103
+ Every writable table on a bound connection exposes the backend-agnostic accessor contract:
104
+
105
+ ```typescript
106
+ const conn = db.from(ctx);
107
+
108
+ const created = await conn.gists.upsert({
109
+ ownerId: 'matt',
110
+ description: 'Hello, Trails',
111
+ });
112
+
113
+ const found = await conn.gists.get(created.id);
114
+ const page = await conn.gists.list({ ownerId: 'matt' }, { limit: 20, offset: 0 });
115
+ const updated = await conn.gists.upsert({
116
+ description: 'Updated description',
117
+ id: created.id,
118
+ ownerId: 'matt',
119
+ });
120
+ const removed = await conn.gists.remove(created.id);
121
+ ```
122
+
123
+ Types are derived from the Zod schema:
124
+
125
+ - `upsert()` uses the fixture/entity shape with generated fields optional
126
+ - `get()` returns `Entity | null`
127
+ - `list()` accepts typed partial filters and pagination options
128
+ - `versioned: true` adds a framework-managed `version` field to returned entities and lets `upsert()` accept an expected `version` for optimistic concurrency
129
+
130
+ Each normalized table also derives typed change signals from the same schema:
131
+
132
+ ```typescript
133
+ const createdHandle = definition.tables.gists.signals.created;
134
+ const updatedHandle = definition.tables.gists.signals.updated;
135
+ const removedHandle = definition.tables.gists.signals.removed;
136
+ ```
137
+
138
+ These pre-bind handles preserve payload shape, but the canonical signal id materializes only when an adapter binds the store to a resource. The bound form is always `resource:table.change`:
139
+
140
+ ```typescript
141
+ const created = db.store.tables.gists.signals.created;
142
+
143
+ created.id;
144
+ // "db.main:gists.created"
145
+ ```
146
+
147
+ ## Adapter Support Subpath
148
+
149
+ Adapter authors who bind a `store(...)` definition to a concrete backend should import signal-binding helpers from `@ontrails/store/adapter-support`:
150
+
151
+ ```typescript
152
+ import { bindStoreDefinition } from '@ontrails/store/adapter-support';
153
+ ```
154
+
155
+ The subpath owns `bindStoreDefinition`, `createStoreTableSignals`, `composeStoreSignalId`, `isValidResourceId`, and `StoreSignalChange`. The root package stays focused on backend-agnostic store contracts.
156
+
157
+ Writable bindings fire those canonical scoped signals automatically when you access the resource through `db.from(ctx)` inside a trail context.
158
+
159
+ See [Store Signal Identity Migration](../../docs/store-signal-identity-migration.md) when updating existing `on:` clauses, surface-map fixtures, or custom resource wrappers from bare ids to scoped ids.
160
+
161
+ Tabular adapters such as `@ontrails/drizzle` also expose `insert()` and `update()` as convenience methods when the backend natively distinguishes create and patch operations.
162
+
163
+ ## Fixtures and mocks
164
+
165
+ Fixtures belong on the root definition:
166
+
167
+ ```typescript
168
+ export const db = store({
169
+ gists: {
170
+ schema: gistSchema,
171
+ identity: 'id',
172
+ generated: ['id', 'createdAt', 'updatedAt'],
173
+ fixtures: [
174
+ { id: 'g_1', ownerId: 'matt', description: 'Seed gist' },
175
+ ],
176
+ },
177
+ });
178
+ ```
179
+
180
+ When an adapter binds the store, those fixtures feed the resource mock automatically. Adapter options can also add or override seed data for tests.
181
+
182
+ That means `testAll(app)` can auto-resolve adapter-bound store resources without extra ceremony, as long as the resource is registered in the topo.
183
+
184
+ ## Read-only bindings
185
+
186
+ Use the Drizzle adapter's read-only binding when a trail should inspect persisted state without exposing writes:
187
+
188
+ ```typescript
189
+ import { connectReadOnlyDrizzle } from '@ontrails/drizzle';
190
+
191
+ const analytics = connectReadOnlyDrizzle(definition, {
192
+ id: 'analytics.db',
193
+ url: './data/analytics.sqlite',
194
+ });
195
+ ```
196
+
197
+ Read-only bindings expose `get()`, `list()`, and `query()`, but not `upsert()`, `remove()`, `insert()`, or `update()`.
198
+
199
+ ## Accessor contract testing
200
+
201
+ Adapters can reuse the shared writable-accessor contract tests from `@ontrails/store/testing`:
202
+
203
+ ```typescript
204
+ import { createStoreAccessorContractCases } from '@ontrails/store/testing';
205
+ ```
206
+
207
+ That helper provides reusable cases for the baseline `get()`, `list()`, `upsert()`, and `remove()` behavior so adapter suites only need to wrap them with their normal `test(...)` calls and add backend-specific coverage on top.
208
+
209
+ ## Drizzle escape hatch
210
+
211
+ Complex queries use the adapter-native query builder through `query()`:
212
+
213
+ ```typescript
214
+ const conn = db.from(ctx);
215
+
216
+ const rows = await conn.query(({ drizzle, tables }) =>
217
+ drizzle
218
+ .select()
219
+ .from(tables.gists)
220
+ );
221
+ ```
222
+
223
+ This keeps the default happy path derived and typed, while still giving you full access to the underlying adapter when the CRUD accessors are not enough.
224
+
225
+ ## Adapter binding
226
+
227
+ `@ontrails/drizzle` keeps the durable `store(...)` declaration in `@ontrails/store` and binds it to a concrete runtime:
228
+
229
+ ```typescript
230
+ import { connectDrizzle, connectReadOnlyDrizzle } from '@ontrails/drizzle';
231
+ import { store } from '@ontrails/store';
232
+
233
+ const definition = store({
234
+ gists: {
235
+ schema: gistSchema,
236
+ identity: 'id',
237
+ generated: ['id', 'createdAt', 'updatedAt'],
238
+ },
239
+ });
240
+
241
+ export const writable = connectDrizzle(definition, { url: ':memory:' });
242
+
243
+ export const readonly = connectReadOnlyDrizzle(definition, {
244
+ url: './data/gists.sqlite',
245
+ });
246
+ ```
247
+
248
+ The root package still owns the authored persistence model; adapter packages render that model into runnable resources.
249
+
250
+ ## Schema export for external tooling
251
+
252
+ If you need the raw derived Drizzle tables for tooling such as `drizzle-kit`, read them from the bound resource's `tables` field:
253
+
254
+ ```typescript
255
+ import { connectDrizzle } from '@ontrails/drizzle';
256
+ import { store } from '@ontrails/store';
257
+
258
+ const definition = store({
259
+ gists: {
260
+ schema: gistSchema,
261
+ identity: 'id',
262
+ generated: ['id', 'createdAt', 'updatedAt'],
263
+ },
264
+ });
265
+
266
+ const db = connectDrizzle(definition, { url: ':memory:' });
267
+ const schema = db.tables;
268
+ ```
269
+
270
+ ## Installation
271
+
272
+ These commands target stable `0.2.0`. Run them after that version is published to npm.
273
+
274
+ ```bash
275
+ bun add --exact @ontrails/store@0.2.0 zod
276
+ ```
277
+
278
+ Add Drizzle only when you want the external SQLite/ORM adapter:
279
+
280
+ ```bash
281
+ bun add --exact @ontrails/drizzle@0.2.0
282
+ ```
283
+
284
+ ## Migration
285
+
286
+ The Drizzle binding now lives in `@ontrails/drizzle`.
287
+
288
+ <!-- warden-ignore-next-line -->
289
+ - Replace `import { ... } from '@ontrails/store/drizzle'` with `import { ... } from '@ontrails/drizzle'`
290
+ - Keep backend-agnostic store declarations on `@ontrails/store`
package/package.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "@ontrails/store",
3
+ "version": "0.2.0",
4
+ "repository": {
5
+ "type": "git",
6
+ "url": "git+https://github.com/outfitter-dev/trails.git",
7
+ "directory": "packages/store"
8
+ },
9
+ "files": [
10
+ "src/**/*.ts",
11
+ "!src/**/__tests__/**",
12
+ "!src/**/*.test.ts",
13
+ "!src/**/*.test-d.ts",
14
+ "README.md",
15
+ "CHANGELOG.md"
16
+ ],
17
+ "type": "module",
18
+ "exports": {
19
+ ".": "./src/index.ts",
20
+ "./adapter-support": "./src/adapter-support.ts",
21
+ "./jsonfile": "./src/jsonfile/index.ts",
22
+ "./trails": "./src/trails/index.ts",
23
+ "./testing": "./src/testing.ts",
24
+ "./package.json": "./package.json"
25
+ },
26
+ "scripts": {
27
+ "build": "tsc -b",
28
+ "test": "bun test",
29
+ "typecheck": "tsc --noEmit",
30
+ "lint": "oxlint ./src",
31
+ "clean": "rm -rf dist *.tsbuildinfo"
32
+ },
33
+ "dependencies": {
34
+ "@ontrails/core": "^0.2.0"
35
+ },
36
+ "peerDependencies": {
37
+ "zod": "^4.3.5"
38
+ },
39
+ "trails": {
40
+ "adapters": {
41
+ "./jsonfile": {
42
+ "target": "store"
43
+ }
44
+ },
45
+ "adapterTargets": {
46
+ "store": {
47
+ "placements": [
48
+ "extracted",
49
+ "subpath"
50
+ ],
51
+ "supportImport": "@ontrails/store/adapter-support",
52
+ "testingImport": "@ontrails/store/testing"
53
+ }
54
+ }
55
+ }
56
+ }