@ontrails/store 1.0.0-beta.15 → 1.0.0-beta.16
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 +36 -0
- package/README.md +31 -15
- package/package.json +11 -3
- package/src/{internal/signal-identity.ts → adapter-support.ts} +15 -14
- package/src/crud-doctrine.ts +43 -0
- package/src/index.ts +6 -1
- package/src/jsonfile/runtime.ts +3 -5
- package/src/jsonfile/types.ts +2 -2
- package/src/store.ts +5 -6
- package/src/testing.ts +2 -2
- package/src/trails/crud.ts +4 -3
- package/src/trails/index.ts +5 -0
- package/src/trails/reconcile.ts +2 -2
- package/src/trails/utils.ts +1 -1
- package/src/types.ts +27 -26
- package/.agents/notes/2026-04-04/handoff-202604032309-9e85a104.md +0 -38
- package/.turbo/turbo-build.log +0 -1
- package/.turbo/turbo-lint.log +0 -3
- package/.turbo/turbo-typecheck.log +0 -1
- package/dist/index.d.ts +0 -3
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -2
- package/dist/index.js.map +0 -1
- package/dist/internal/signal-identity.d.ts +0 -17
- package/dist/internal/signal-identity.d.ts.map +0 -1
- package/dist/internal/signal-identity.js +0 -81
- package/dist/internal/signal-identity.js.map +0 -1
- package/dist/jsonfile/index.d.ts +0 -3
- package/dist/jsonfile/index.d.ts.map +0 -1
- package/dist/jsonfile/index.js +0 -2
- package/dist/jsonfile/index.js.map +0 -1
- package/dist/jsonfile/runtime.d.ts +0 -19
- package/dist/jsonfile/runtime.d.ts.map +0 -1
- package/dist/jsonfile/runtime.js +0 -403
- package/dist/jsonfile/runtime.js.map +0 -1
- package/dist/jsonfile/types.d.ts +0 -40
- package/dist/jsonfile/types.d.ts.map +0 -1
- package/dist/jsonfile/types.js +0 -2
- package/dist/jsonfile/types.js.map +0 -1
- package/dist/store.d.ts +0 -16
- package/dist/store.d.ts.map +0 -1
- package/dist/store.js +0 -250
- package/dist/store.js.map +0 -1
- package/dist/testing.d.ts +0 -28
- package/dist/testing.d.ts.map +0 -1
- package/dist/testing.js +0 -90
- package/dist/testing.js.map +0 -1
- package/dist/trails/crud.d.ts +0 -38
- package/dist/trails/crud.d.ts.map +0 -1
- package/dist/trails/crud.js +0 -112
- package/dist/trails/crud.js.map +0 -1
- package/dist/trails/index.d.ts +0 -7
- package/dist/trails/index.d.ts.map +0 -1
- package/dist/trails/index.js +0 -4
- package/dist/trails/index.js.map +0 -1
- package/dist/trails/reconcile.d.ts +0 -36
- package/dist/trails/reconcile.d.ts.map +0 -1
- package/dist/trails/reconcile.js +0 -142
- package/dist/trails/reconcile.js.map +0 -1
- package/dist/trails/sync.d.ts +0 -25
- package/dist/trails/sync.d.ts.map +0 -1
- package/dist/trails/sync.js +0 -96
- package/dist/trails/sync.js.map +0 -1
- package/dist/trails/utils.d.ts +0 -51
- package/dist/trails/utils.d.ts.map +0 -1
- package/dist/trails/utils.js +0 -65
- package/dist/trails/utils.js.map +0 -1
- package/dist/types.d.ts +0 -394
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -2
- package/dist/types.js.map +0 -1
- package/src/__tests__/crud.test.ts +0 -346
- package/src/__tests__/jsonfile.test.ts +0 -502
- package/src/__tests__/store.test.ts +0 -539
- package/src/__tests__/sync-reconcile.test.ts +0 -646
- package/tsconfig.json +0 -9
- package/tsconfig.tests.json +0 -10
- package/tsconfig.tsbuildinfo +0 -1
package/src/types.ts
CHANGED
|
@@ -3,7 +3,7 @@ import type { StoreAccessorProtocol } from '@ontrails/core/store';
|
|
|
3
3
|
import type { z } from 'zod';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
* Backend-agnostic persistence shapes that
|
|
6
|
+
* Backend-agnostic persistence shapes that an adapter can interpret.
|
|
7
7
|
*/
|
|
8
8
|
export type StoreKind = 'tabular' | 'document' | 'file' | 'kv' | 'cache';
|
|
9
9
|
|
|
@@ -133,10 +133,10 @@ export type StoreFixtureRow<
|
|
|
133
133
|
: never;
|
|
134
134
|
|
|
135
135
|
/**
|
|
136
|
-
*
|
|
136
|
+
* Adapter-owned search metadata.
|
|
137
137
|
*
|
|
138
138
|
* The core package keeps this opaque on purpose. Search behavior is declared
|
|
139
|
-
* here and interpreted by a concrete
|
|
139
|
+
* here and interpreted by a concrete adapter later.
|
|
140
140
|
*/
|
|
141
141
|
export type StoreSearchDefinition = Readonly<Record<string, unknown>>;
|
|
142
142
|
|
|
@@ -353,7 +353,7 @@ export interface StoreDefinition<
|
|
|
353
353
|
/**
|
|
354
354
|
* Structural view of any normalized store table.
|
|
355
355
|
*
|
|
356
|
-
* This stays broad on purpose so
|
|
356
|
+
* This stays broad on purpose so adapter packages can accept concrete store
|
|
357
357
|
* definitions returned by `store(...)` without erasing their table-specific
|
|
358
358
|
* types back to one canonical generic instantiation.
|
|
359
359
|
*/
|
|
@@ -455,8 +455,8 @@ export type UpdateOf<TTable extends AnyStoreTable> = Partial<
|
|
|
455
455
|
/**
|
|
456
456
|
* Upsert shape: entity payload with generated fields remaining optional.
|
|
457
457
|
*
|
|
458
|
-
* This matches the
|
|
459
|
-
* still allowing
|
|
458
|
+
* This matches the backend-agnostic "create or replace" contract while
|
|
459
|
+
* still allowing adapters to synthesize generated values like IDs and
|
|
460
460
|
* timestamps when the caller omits them.
|
|
461
461
|
*/
|
|
462
462
|
export type UpsertOf<TTable extends AnyStoreTable> = FixtureInputOf<TTable>;
|
|
@@ -502,7 +502,7 @@ export interface ReadOnlyStoreTableAccessor<TTable extends AnyStoreTable> {
|
|
|
502
502
|
}
|
|
503
503
|
|
|
504
504
|
/**
|
|
505
|
-
*
|
|
505
|
+
* Backend-agnostic writable operations layered on top of the read contract.
|
|
506
506
|
*/
|
|
507
507
|
export interface StoreAccessor<
|
|
508
508
|
TTable extends AnyStoreTable,
|
|
@@ -513,11 +513,11 @@ export interface StoreAccessor<
|
|
|
513
513
|
* @throws {AlreadyExistsError} On primary key or unique constraint violation.
|
|
514
514
|
*
|
|
515
515
|
* @remarks
|
|
516
|
-
* This is an intentional throw-based boundary: store
|
|
516
|
+
* This is an intentional throw-based boundary: store adapters throw typed
|
|
517
517
|
* errors (`AlreadyExistsError`) rather than returning `Result`. Trail
|
|
518
518
|
* implementations that call store accessors should catch and convert to
|
|
519
519
|
* `Result.err()` at their level. A future safe variant returning `Result`
|
|
520
|
-
* is planned but deferred to avoid cascading changes across all
|
|
520
|
+
* is planned but deferred to avoid cascading changes across all adapters.
|
|
521
521
|
*/
|
|
522
522
|
upsert(input: UpsertOf<TTable>): Promise<EntityOf<TTable>>;
|
|
523
523
|
/**
|
|
@@ -545,12 +545,11 @@ type AssertExtends<TActual, TExpected> = TActual extends TExpected
|
|
|
545
545
|
|
|
546
546
|
/**
|
|
547
547
|
* Pins the structural relationship between `StoreAccessor` and the core
|
|
548
|
-
* `StoreAccessorProtocol`.
|
|
549
|
-
*
|
|
550
|
-
* this
|
|
551
|
-
* the store accessor contract — fix the protocol shape, not this assertion.
|
|
548
|
+
* `StoreAccessorProtocol`. If this check resolves to `never`, the protocol in
|
|
549
|
+
* core has drifted from the store accessor contract — fix the protocol shape,
|
|
550
|
+
* not this assertion.
|
|
552
551
|
*/
|
|
553
|
-
|
|
552
|
+
const storeAccessorProtocolCheck: AssertExtends<
|
|
554
553
|
StoreAccessor<AnyStoreTable>,
|
|
555
554
|
StoreAccessorProtocol<
|
|
556
555
|
UpsertOf<AnyStoreTable>,
|
|
@@ -558,10 +557,12 @@ export type AssertStoreAccessorSatisfiesProtocol = AssertExtends<
|
|
|
558
557
|
StoreIdentifierOf<AnyStoreTable>,
|
|
559
558
|
FiltersOf<AnyStoreTable>
|
|
560
559
|
>
|
|
561
|
-
|
|
560
|
+
> = true;
|
|
561
|
+
|
|
562
|
+
void storeAccessorProtocolCheck;
|
|
562
563
|
|
|
563
564
|
/**
|
|
564
|
-
* Tabular writable operations layered on top of the
|
|
565
|
+
* Tabular writable operations layered on top of the backend-agnostic
|
|
565
566
|
* contract.
|
|
566
567
|
*/
|
|
567
568
|
export interface StoreTableAccessor<
|
|
@@ -570,7 +571,7 @@ export interface StoreTableAccessor<
|
|
|
570
571
|
/**
|
|
571
572
|
* Insert a new entity.
|
|
572
573
|
*
|
|
573
|
-
* Tabular
|
|
574
|
+
* Tabular adapters can expose this convenience when the backend has a
|
|
574
575
|
* native distinction between create and update.
|
|
575
576
|
*/
|
|
576
577
|
insert(input: InsertOf<TTable>): Promise<EntityOf<TTable>>;
|
|
@@ -582,8 +583,8 @@ export interface StoreTableAccessor<
|
|
|
582
583
|
* On versioned tables, `update` does **not** participate in optimistic
|
|
583
584
|
* concurrency control. The `UpdateOf<TTable>` shape is derived by omitting
|
|
584
585
|
* generated fields — including the framework-managed `version` column — so
|
|
585
|
-
* any `version` value is dropped before reaching the
|
|
586
|
-
*
|
|
586
|
+
* any `version` value is dropped before reaching the adapter and the
|
|
587
|
+
* adapter always auto-increments without comparing. Callers that need
|
|
587
588
|
* lost-update protection must use {@link StoreAccessor.upsert | `upsert`}
|
|
588
589
|
* instead and pass the expected `version` in the payload.
|
|
589
590
|
*/
|
|
@@ -603,7 +604,7 @@ export type ReadOnlyStoreConnection<TStore extends AnyStoreDefinition> = {
|
|
|
603
604
|
};
|
|
604
605
|
|
|
605
606
|
/**
|
|
606
|
-
*
|
|
607
|
+
* Backend-agnostic connection shape exposed by a writable bound store.
|
|
607
608
|
*/
|
|
608
609
|
export type StoreConnection<TStore extends AnyStoreDefinition> = {
|
|
609
610
|
readonly [TName in keyof TStore['tables']]: StoreAccessor<
|
|
@@ -612,7 +613,7 @@ export type StoreConnection<TStore extends AnyStoreDefinition> = {
|
|
|
612
613
|
};
|
|
613
614
|
|
|
614
615
|
/**
|
|
615
|
-
* Tabular connection shape exposed by
|
|
616
|
+
* Tabular connection shape exposed by adapters that distinguish insert and
|
|
616
617
|
* patch operations from the generalized `upsert` contract.
|
|
617
618
|
*/
|
|
618
619
|
export type StoreTableConnection<TStore extends AnyStoreDefinition> = {
|
|
@@ -625,7 +626,7 @@ export type StoreTableConnection<TStore extends AnyStoreDefinition> = {
|
|
|
625
626
|
* Optional fixture overrides used when building a mock store connection.
|
|
626
627
|
*
|
|
627
628
|
* The shape is a partial map keyed by table name; each entry is a list of
|
|
628
|
-
* fixture inputs validated against the table's fixture schema.
|
|
629
|
+
* fixture inputs validated against the table's fixture schema. Adapters
|
|
629
630
|
* share this type so every store backend seeds mocks the same way.
|
|
630
631
|
*/
|
|
631
632
|
export type StoreMockSeed<TDef extends AnyStoreDefinition> = Partial<{
|
|
@@ -635,13 +636,13 @@ export type StoreMockSeed<TDef extends AnyStoreDefinition> = Partial<{
|
|
|
635
636
|
}>;
|
|
636
637
|
|
|
637
638
|
/**
|
|
638
|
-
* Shared
|
|
639
|
+
* Shared adapter options every store backend accepts.
|
|
639
640
|
*
|
|
640
|
-
* Concrete
|
|
641
|
+
* Concrete adapters extend this shape with their backend-specific fields
|
|
641
642
|
* (e.g. `url`, `dir`). Aligning the authored surface here lets the framework
|
|
642
|
-
* reason about
|
|
643
|
+
* reason about adapter options uniformly — one shape, many projections.
|
|
643
644
|
*/
|
|
644
|
-
export interface
|
|
645
|
+
export interface StoreAdapterOptions<TDef extends AnyStoreDefinition> {
|
|
645
646
|
/** Optional resource id override. Defaults to `"store"`. */
|
|
646
647
|
readonly id?: string;
|
|
647
648
|
/** Human-readable description surfaced on the resource definition. */
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
created: 2026-04-04T03:09:15.424Z
|
|
3
|
-
type: handoff
|
|
4
|
-
session: 9e85a104-864f-4273-b68d-a4a95eb2d5fc
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# Handoff 2026-04-04 23:09
|
|
8
|
-
|
|
9
|
-
> Session `9e85a104` — PR feedback loop on 14-branch Graphite stack (#64-#77)
|
|
10
|
-
|
|
11
|
-
## Done
|
|
12
|
-
|
|
13
|
-
- **Round 1**: Fixed 11 P1s across the stack — `persistEstablishedTopoSave` throw→Result, hash pipeline unification in drift.ts, store type safety (nullable defaults, PK leak, InsertOf/UpdateOf precision), drizzle error mapping, legacy tracker DB cleanup, transitive cache TSDoc, duplicate const before compile error
|
|
14
|
-
- **Round 2**: Fixed absorb regressions (variable reference splits across branches), plus new P1s — Commander undefined opts, toTrackStore close() no-op, verifyCurrentTopo hash pipeline, duplicate verifyCurrentTopo removal
|
|
15
|
-
- **Round 3**: Fixed remaining P1s — ADR depends_on slug→integer normalization, draft-promote preflight rename validation (duplicates + existing targets), NOT NULL on PK columns in generated SQL, InternalError passthrough, warden README method names (.trailhead→.blaze), vocabulary verb fix
|
|
16
|
-
- **Thread resolution**: 128 threads resolved across 3 rounds, re-reviews requested each time
|
|
17
|
-
- **Key learning**: `gt absorb` splits changes across branches unpredictably when a function definition and its callers span different branches — always walk up and typecheck each branch after absorb
|
|
18
|
-
|
|
19
|
-
## State
|
|
20
|
-
|
|
21
|
-
- On branch `trl-129-topo-and-dev-surfaces` (#69) with an uncommitted fix (drift.ts resolveTrailsDir import + readTrailheadLock dir fix) — lint failed, needs investigation
|
|
22
|
-
- 4 new P1s surfaced in Round 4 (from `-p 2` run which includes P0-P2):
|
|
23
|
-
- **#69**: drift.ts passes workspace root instead of `.trails/` to readTrailheadLock (fix attempted, lint error pending)
|
|
24
|
-
- **#71**: v2→v3 migration gap in topo-saves.ts — crash on existing schema version 2 databases
|
|
25
|
-
- **#72**: createMockTopoStore returns data without seeded saves (diverges from real store)
|
|
26
|
-
- **#77**: Three broken API examples in warden README (wrong signatures, invalid lefthook key)
|
|
27
|
-
- P2s not yet addressed across #65, #68, #70, #72, #75
|
|
28
|
-
|
|
29
|
-
## Next
|
|
30
|
-
|
|
31
|
-
- [ ] Debug lint failure on #69 drift.ts fix and commit
|
|
32
|
-
- [ ] Fix #71: Add v2→v3 migration guard in `ensureTopoHistorySchema` to create `topo_schemas`/`topo_exports` tables
|
|
33
|
-
- [ ] Fix #72: Add empty-save guard to `createMockTopoStore` `trails.list()`/`trails.get()`
|
|
34
|
-
- [ ] Fix #77: Correct `runWarden` and `checkDrift` signatures + lefthook key in warden README
|
|
35
|
-
- [ ] Walk up all branches verifying typecheck after each fix
|
|
36
|
-
- [ ] Submit stack, resolve threads, write loop record
|
|
37
|
-
- [ ] Then address P2s: gitignore duplicate-append (#68), stale TSDoc (#70), test harness fallback (#65), readonlyStore mock factory (#75)
|
|
38
|
-
- [ ] Consider: the `isDraftMarkedFile` vs `stripDraftFileMarkers` inconsistency on #67 is still open (P2)
|
package/.turbo/turbo-build.log
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
$ tsc -b
|
package/.turbo/turbo-lint.log
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
$ tsc --noEmit
|
package/dist/index.d.ts
DELETED
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
export { store, versionFieldName } from './store.js';
|
|
2
|
-
export type { AnyStoreDefinition, AnyStoreTable, EntityOf, FiltersOf, FixtureInputOf, FixtureOf, FixturesOfInput, GeneratedFieldsOfInput, GeneratedKeysOf, IdentityFieldOfInput, IdentityOf, IndexFieldsOfInput, IndexedFieldsOfInput, InsertOf, ReadOnlyStoreConnection, StoreAccessor, ReadOnlyStoreTableAccessor, ReferencesOfInput, StoreAccessMode, StoreConnection, StoreConnectorOptions, StoreDefinition, StoreFieldKey, StoreFixtureInput, StoreFixtureRow, StoreIdentifierOf, StoreKind, StoreListOptions, StoreMockSeed, StoreObjectSchema, StoreOptions, StoreSearchDefinition, StoreTable, StoreTableSignals, StoreTableAccessor, StoreTableConnection, StoreTableInput, StoreTablesInput, UpsertOf, UpdateOf, } from './types.js';
|
|
3
|
-
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACrD,YAAY,EACV,kBAAkB,EAClB,aAAa,EACb,QAAQ,EACR,SAAS,EACT,cAAc,EACd,SAAS,EACT,eAAe,EACf,sBAAsB,EACtB,eAAe,EACf,oBAAoB,EACpB,UAAU,EACV,kBAAkB,EAClB,oBAAoB,EACpB,QAAQ,EACR,uBAAuB,EACvB,aAAa,EACb,0BAA0B,EAC1B,iBAAiB,EACjB,eAAe,EACf,eAAe,EACf,qBAAqB,EACrB,eAAe,EACf,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,iBAAiB,EACjB,SAAS,EACT,gBAAgB,EAChB,aAAa,EACb,iBAAiB,EACjB,YAAY,EACZ,qBAAqB,EACrB,UAAU,EACV,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,EACpB,eAAe,EACf,gBAAgB,EAChB,QAAQ,EACR,QAAQ,GACT,MAAM,YAAY,CAAC"}
|
package/dist/index.js
DELETED
package/dist/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import type { z } from 'zod';
|
|
2
|
-
import type { AnyStoreDefinition, StoreTableSignals } from '../types.js';
|
|
3
|
-
type StoreSignalEvent = 'created' | 'removed' | 'updated';
|
|
4
|
-
export declare const createStoreTableSignals: <TPayload>(tableName: string, payload: z.ZodType<TPayload>) => StoreTableSignals<TPayload>;
|
|
5
|
-
export declare const composeStoreSignalId: (scope: string, tableName: string, event: StoreSignalEvent) => string;
|
|
6
|
-
/**
|
|
7
|
-
* Verifies that a resource id is safe to compose into a scoped signal id.
|
|
8
|
-
*
|
|
9
|
-
* Scoped signal ids are matched by the `SCOPED_SIGNAL_ID` pattern in
|
|
10
|
-
* `@ontrails/core` (`^[^:\s]+:[^:.\s]+(?:\.[^:.\s]+)+$`). A resource id used
|
|
11
|
-
* as the scope segment must therefore be a non-empty string that contains
|
|
12
|
-
* neither `":"` nor any whitespace.
|
|
13
|
-
*/
|
|
14
|
-
export declare const isValidResourceId: (resourceId: string) => boolean;
|
|
15
|
-
export declare const bindStoreDefinition: <TStore extends AnyStoreDefinition>(definition: TStore, scope: string) => TStore;
|
|
16
|
-
export type { StoreSignalEvent };
|
|
17
|
-
//# sourceMappingURL=signal-identity.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"signal-identity.d.ts","sourceRoot":"","sources":["../../src/internal/signal-identity.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAE7B,OAAO,KAAK,EACV,kBAAkB,EAElB,iBAAiB,EAClB,MAAM,aAAa,CAAC;AAMrB,KAAK,gBAAgB,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;AAsC1D,eAAO,MAAM,uBAAuB,GAAI,QAAQ,EAC9C,WAAW,MAAM,EACjB,SAAS,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,KAC3B,iBAAiB,CAAC,QAAQ,CAKzB,CAAC;AAEL,eAAO,MAAM,oBAAoB,GAC/B,OAAO,MAAM,EACb,WAAW,MAAM,EACjB,OAAO,gBAAgB,KACtB,MAA0C,CAAC;AAkC9C;;;;;;;GAOG;AACH,eAAO,MAAM,iBAAiB,GAAI,YAAY,MAAM,KAAG,OACuB,CAAC;AAU/E,eAAO,MAAM,mBAAmB,GAAI,MAAM,SAAS,kBAAkB,EACnE,YAAY,MAAM,EAClB,OAAO,MAAM,KACZ,MAiCF,CAAC;AAEF,YAAY,EAAE,gBAAgB,EAAE,CAAC"}
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
import { signal, ValidationError } from '@ontrails/core';
|
|
2
|
-
import { attachLateBoundSignalRef, cloneSignalWithId, } from '@ontrails/core/internal/signal-ref';
|
|
3
|
-
const createStoreSignalDescription = (tableName, event) => {
|
|
4
|
-
switch (event) {
|
|
5
|
-
case 'created': {
|
|
6
|
-
return `Fired after a "${tableName}" entity is created.`;
|
|
7
|
-
}
|
|
8
|
-
case 'removed': {
|
|
9
|
-
return `Fired after a "${tableName}" entity is removed.`;
|
|
10
|
-
}
|
|
11
|
-
case 'updated': {
|
|
12
|
-
return `Fired after a "${tableName}" entity is updated.`;
|
|
13
|
-
}
|
|
14
|
-
default: {
|
|
15
|
-
throw new Error(`Unsupported store signal event: ${event}`);
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
};
|
|
19
|
-
const createStoreSignal = (tableName, event, payload) => attachLateBoundSignalRef(signal(`${tableName}.${event}`, {
|
|
20
|
-
description: createStoreSignalDescription(tableName, event),
|
|
21
|
-
payload,
|
|
22
|
-
}), {
|
|
23
|
-
kind: 'store-derived',
|
|
24
|
-
token: Bun.randomUUIDv7(),
|
|
25
|
-
});
|
|
26
|
-
export const createStoreTableSignals = (tableName, payload) => Object.freeze({
|
|
27
|
-
created: createStoreSignal(tableName, 'created', payload),
|
|
28
|
-
removed: createStoreSignal(tableName, 'removed', payload),
|
|
29
|
-
updated: createStoreSignal(tableName, 'updated', payload),
|
|
30
|
-
});
|
|
31
|
-
export const composeStoreSignalId = (scope, tableName, event) => `${scope}:${tableName}.${event}`;
|
|
32
|
-
const bindTableSignals = (scope, table) => Object.freeze({
|
|
33
|
-
created: cloneSignalWithId(table.signals.created, composeStoreSignalId(scope, table.name, 'created')),
|
|
34
|
-
removed: cloneSignalWithId(table.signals.removed, composeStoreSignalId(scope, table.name, 'removed')),
|
|
35
|
-
updated: cloneSignalWithId(table.signals.updated, composeStoreSignalId(scope, table.name, 'updated')),
|
|
36
|
-
});
|
|
37
|
-
const collectStoreSignals = (normalized, tableNames) => Object.freeze(tableNames.flatMap((name) => {
|
|
38
|
-
const table = normalized[name];
|
|
39
|
-
return table === undefined
|
|
40
|
-
? []
|
|
41
|
-
: [table.signals.created, table.signals.updated, table.signals.removed];
|
|
42
|
-
}));
|
|
43
|
-
/**
|
|
44
|
-
* Verifies that a resource id is safe to compose into a scoped signal id.
|
|
45
|
-
*
|
|
46
|
-
* Scoped signal ids are matched by the `SCOPED_SIGNAL_ID` pattern in
|
|
47
|
-
* `@ontrails/core` (`^[^:\s]+:[^:.\s]+(?:\.[^:.\s]+)+$`). A resource id used
|
|
48
|
-
* as the scope segment must therefore be a non-empty string that contains
|
|
49
|
-
* neither `":"` nor any whitespace.
|
|
50
|
-
*/
|
|
51
|
-
export const isValidResourceId = (resourceId) => resourceId.length > 0 && !resourceId.includes(':') && !/\s/.test(resourceId);
|
|
52
|
-
const assertValidScope = (scope) => {
|
|
53
|
-
if (!isValidResourceId(scope)) {
|
|
54
|
-
throw new ValidationError(`Store resource id "${scope}" is invalid: must be a non-empty string with no ":" characters and no whitespace.`);
|
|
55
|
-
}
|
|
56
|
-
};
|
|
57
|
-
export const bindStoreDefinition = (definition, scope) => {
|
|
58
|
-
assertValidScope(scope);
|
|
59
|
-
const tableNames = definition.tableNames;
|
|
60
|
-
const tables = {};
|
|
61
|
-
for (const tableName of tableNames) {
|
|
62
|
-
const table = definition.tables[tableName];
|
|
63
|
-
if (table === undefined) {
|
|
64
|
-
continue;
|
|
65
|
-
}
|
|
66
|
-
tables[tableName] = Object.freeze({
|
|
67
|
-
...table,
|
|
68
|
-
signals: bindTableSignals(scope, table),
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
const get = 'get' in definition && typeof definition.get === 'function'
|
|
72
|
-
? (name) => tables[name]
|
|
73
|
-
: undefined;
|
|
74
|
-
return Object.freeze({
|
|
75
|
-
...definition,
|
|
76
|
-
...(get ? { get } : {}),
|
|
77
|
-
signals: collectStoreSignals(tables, tableNames),
|
|
78
|
-
tables: Object.freeze(tables),
|
|
79
|
-
});
|
|
80
|
-
};
|
|
81
|
-
//# sourceMappingURL=signal-identity.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"signal-identity.js","sourceRoot":"","sources":["../../src/internal/signal-identity.ts"],"names":[],"mappings":"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"}
|
package/dist/jsonfile/index.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/jsonfile/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,QAAQ,IAAI,KAAK,EAAE,MAAM,cAAc,CAAC;AAC5E,YAAY,EACV,kBAAkB,EAClB,oBAAoB,EACpB,qBAAqB,GACtB,MAAM,YAAY,CAAC"}
|
package/dist/jsonfile/index.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/jsonfile/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,QAAQ,IAAI,KAAK,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import type { AnyStoreDefinition } from '../types.js';
|
|
2
|
-
import type { JsonFileConnection, JsonFileStoreOptions, JsonFileStoreResource } from './types.js';
|
|
3
|
-
/**
|
|
4
|
-
* Connect to a JSON-file-backed store.
|
|
5
|
-
*
|
|
6
|
-
* Creates one `<tableName>.json` file per table in the target directory.
|
|
7
|
-
* Each file holds a JSON array of entities. The entire dataset is loaded
|
|
8
|
-
* into memory on connect and flushed to disk on every write.
|
|
9
|
-
*/
|
|
10
|
-
export declare const connectJsonFile: <TStore extends AnyStoreDefinition>(definition: TStore, options: JsonFileStoreOptions<TStore>) => Promise<JsonFileConnection<TStore["tables"]>>;
|
|
11
|
-
/**
|
|
12
|
-
* Create a JSON-file-backed store resource.
|
|
13
|
-
*
|
|
14
|
-
* Returns a `Resource` that can be registered in a topo and resolved from
|
|
15
|
-
* trail context via `db.from(ctx)`.
|
|
16
|
-
*/
|
|
17
|
-
export declare const jsonFile: <TStore extends AnyStoreDefinition>(definition: TStore, options: JsonFileStoreOptions<TStore>) => JsonFileStoreResource<TStore["tables"]>;
|
|
18
|
-
export { jsonFile as store };
|
|
19
|
-
//# sourceMappingURL=runtime.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/jsonfile/runtime.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,kBAAkB,EASnB,MAAM,aAAa,CAAC;AAIrB,OAAO,KAAK,EACV,kBAAkB,EAClB,oBAAoB,EACpB,qBAAqB,EACtB,MAAM,YAAY,CAAC;AAglBpB;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,GAAU,MAAM,SAAS,kBAAkB,EACrE,YAAY,MAAM,EAClB,SAAS,oBAAoB,CAAC,MAAM,CAAC,KACpC,OAAO,CAAC,kBAAkB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAmB9C,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,QAAQ,GAAI,MAAM,SAAS,kBAAkB,EACxD,YAAY,MAAM,EAClB,SAAS,oBAAoB,CAAC,MAAM,CAAC,KACpC,qBAAqB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAgDxC,CAAC;AAEF,OAAO,EAAE,QAAQ,IAAI,KAAK,EAAE,CAAC"}
|