@haverstack/core 0.11.1 → 0.11.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/dist/access.d.ts +9 -1
- package/dist/access.d.ts.map +1 -1
- package/dist/access.js +35 -9
- package/dist/access.js.map +1 -1
- package/dist/changes.d.ts +105 -0
- package/dist/changes.d.ts.map +1 -0
- package/dist/changes.js +228 -0
- package/dist/changes.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/stack.d.ts +98 -44
- package/dist/stack.d.ts.map +1 -1
- package/dist/stack.js +497 -69
- package/dist/stack.js.map +1 -1
- package/dist/testing.d.ts +15 -9
- package/dist/testing.d.ts.map +1 -1
- package/dist/testing.js +45 -21
- package/dist/testing.js.map +1 -1
- package/dist/types.d.ts +158 -10
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +2 -2
package/dist/access.d.ts
CHANGED
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
* storage backend. Used by ScopedStack (see stack.ts) to enforce access
|
|
7
7
|
* control; exported standalone for callers that want the raw predicate.
|
|
8
8
|
*/
|
|
9
|
-
import type { Association, EntityId, RecordId, StackRecord } from './types.js';
|
|
9
|
+
import type { Association, EntityId, Permission, RecordId, StackRecord } from './types.js';
|
|
10
|
+
import type { ValidationError } from './validate.js';
|
|
10
11
|
export type AccessMode = 'read' | 'write';
|
|
11
12
|
/** An entity's standing within a `_group` Record's roster. `admin` implies `member` for ACL purposes. */
|
|
12
13
|
export type GroupRole = 'member' | 'admin';
|
|
@@ -28,6 +29,13 @@ export type RecordResolver = (id: RecordId) => Promise<StackRecord | null>;
|
|
|
28
29
|
* subject.
|
|
29
30
|
*/
|
|
30
31
|
export declare function checkAccess(record: StackRecord, subjectEntityId: EntityId | null, ownerEntityId: EntityId | null, mode: AccessMode, resolveRecord: RecordResolver): Promise<boolean>;
|
|
32
|
+
/**
|
|
33
|
+
* Rejects permission entries that convey write without read — the shape
|
|
34
|
+
* entryConveys() refuses to honor, caught at the point of storage so an
|
|
35
|
+
* owner writing one is told rather than left with a bit that does nothing.
|
|
36
|
+
* See docs/spec/access-control.md § Write implies read.
|
|
37
|
+
*/
|
|
38
|
+
export declare function validatePermissions(permissions: Permission[] | undefined, path?: string): ValidationError[];
|
|
31
39
|
/**
|
|
32
40
|
* Determine an entity's role within a `_group` Record's roster from its
|
|
33
41
|
* relationship associations. `admin` short-circuits — it's strictly more
|
package/dist/access.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"access.d.ts","sourceRoot":"","sources":["../src/access.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"access.d.ts","sourceRoot":"","sources":["../src/access.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC3F,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAErD,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,OAAO,CAAC;AAE1C,yGAAyG;AACzG,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,OAAO,CAAC;AAE3C;;;GAGG;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,EAAE,EAAE,QAAQ,KAAK,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;AAE3E;;;;;;;;;;;GAWG;AACH,wBAAsB,WAAW,CAC/B,MAAM,EAAE,WAAW,EACnB,eAAe,EAAE,QAAQ,GAAG,IAAI,EAChC,aAAa,EAAE,QAAQ,GAAG,IAAI,EAC9B,IAAI,EAAE,UAAU,EAChB,aAAa,EAAE,cAAc,GAC5B,OAAO,CAAC,OAAO,CAAC,CAwBlB;AAeD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,WAAW,EAAE,UAAU,EAAE,GAAG,SAAS,EACrC,IAAI,SAAgB,GACnB,eAAe,EAAE,CAanB;AAYD;;;;;GAKG;AACH,wBAAgB,yBAAyB,CACvC,YAAY,EAAE,WAAW,EAAE,GAAG,SAAS,EACvC,QAAQ,EAAE,QAAQ,GACjB,SAAS,GAAG,IAAI,CASlB"}
|
package/dist/access.js
CHANGED
|
@@ -30,24 +30,50 @@ export async function checkAccess(record, subjectEntityId, ownerEntityId, mode,
|
|
|
30
30
|
if (p.access === 'public' && mode === 'read')
|
|
31
31
|
return true;
|
|
32
32
|
if (p.access === 'entity' && p.entityId === subjectEntityId) {
|
|
33
|
-
if (mode
|
|
34
|
-
return true;
|
|
35
|
-
if (mode === 'write' && p.write)
|
|
33
|
+
if (entryConveys(p, mode))
|
|
36
34
|
return true;
|
|
37
35
|
}
|
|
38
36
|
if (p.access === 'group' && subjectEntityId) {
|
|
39
37
|
const role = await resolveGroupRole(p.groupId, subjectEntityId, resolveRecord);
|
|
40
38
|
const satisfiesRole = p.role === 'admin' ? role === 'admin' : role !== null;
|
|
41
|
-
if (satisfiesRole)
|
|
42
|
-
|
|
43
|
-
return true;
|
|
44
|
-
if (mode === 'write' && p.write)
|
|
45
|
-
return true;
|
|
46
|
-
}
|
|
39
|
+
if (satisfiesRole && entryConveys(p, mode))
|
|
40
|
+
return true;
|
|
47
41
|
}
|
|
48
42
|
}
|
|
49
43
|
return false;
|
|
50
44
|
}
|
|
45
|
+
/**
|
|
46
|
+
* Whether an entry the requester already matches conveys `mode`. The write
|
|
47
|
+
* bit is inert without read alongside it: the mutate surface hands back the
|
|
48
|
+
* record it wrote and opens its whole history, so a write bit without read
|
|
49
|
+
* would disclose exactly what withholding read asks to withhold. Refused at
|
|
50
|
+
* the write by validatePermissions() and again here, since a `permissions`
|
|
51
|
+
* array can also arrive from an import or a foreign server. See
|
|
52
|
+
* docs/spec/access-control.md § Write implies read.
|
|
53
|
+
*/
|
|
54
|
+
function entryConveys(p, mode) {
|
|
55
|
+
return mode === 'read' ? p.read : p.write && p.read;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Rejects permission entries that convey write without read — the shape
|
|
59
|
+
* entryConveys() refuses to honor, caught at the point of storage so an
|
|
60
|
+
* owner writing one is told rather than left with a bit that does nothing.
|
|
61
|
+
* See docs/spec/access-control.md § Write implies read.
|
|
62
|
+
*/
|
|
63
|
+
export function validatePermissions(permissions, path = 'permissions') {
|
|
64
|
+
const errors = [];
|
|
65
|
+
(permissions ?? []).forEach((p, i) => {
|
|
66
|
+
if (p.access === 'public')
|
|
67
|
+
return;
|
|
68
|
+
if (p.write && !p.read) {
|
|
69
|
+
errors.push({
|
|
70
|
+
path: `${path}[${i}]`,
|
|
71
|
+
message: 'write requires read: a write-holder reaches the record and its history through the mutate surface, so `write: true, read: false` withholds nothing',
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
return errors;
|
|
76
|
+
}
|
|
51
77
|
async function resolveGroupRole(groupRecordId, entityId, resolveRecord) {
|
|
52
78
|
const group = await resolveRecord(groupRecordId);
|
|
53
79
|
if (!group)
|
package/dist/access.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"access.js","sourceRoot":"","sources":["../src/access.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;
|
|
1
|
+
{"version":3,"file":"access.js","sourceRoot":"","sources":["../src/access.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stack — Change Events
|
|
3
|
+
* -------------------------------------------------------
|
|
4
|
+
* The emitter behind StackClient.subscribe(): a subscriber registry, the
|
|
5
|
+
* filter predicate, and the projection that turns what the emitter knows
|
|
6
|
+
* into what a subscriber is allowed to see.
|
|
7
|
+
*
|
|
8
|
+
* The split between those last two is the point of this module. Emission
|
|
9
|
+
* always carries the record — a permission filter has nothing to decide
|
|
10
|
+
* with otherwise, and on a hard delete there is nothing left to fetch —
|
|
11
|
+
* while the frame handed to a handler is projected from it. So the rule
|
|
12
|
+
* that a purge discloses neither the record nor its provenance is a
|
|
13
|
+
* property of one function here, not a convention every emission site has
|
|
14
|
+
* to remember. See docs/spec/events.md.
|
|
15
|
+
*/
|
|
16
|
+
import type { ChangeActor, ChangeFilter, ChangeKind, ChangeOp, RecordChange, StackRecord, SubscribeOptions, Unsubscribe } from './types.js';
|
|
17
|
+
/**
|
|
18
|
+
* What the emitter knows: the envelope, plus the record it describes.
|
|
19
|
+
* `record` is the filtering input and is never delivered unprojected —
|
|
20
|
+
* emitted() is the only way out.
|
|
21
|
+
*/
|
|
22
|
+
export type EmittedChange = {
|
|
23
|
+
change: Omit<RecordChange, 'record'>;
|
|
24
|
+
/**
|
|
25
|
+
* The record as of the change; for `purged`, as it stood immediately
|
|
26
|
+
* before destruction. Present for every emission, including the ones
|
|
27
|
+
* whose frames must not carry it.
|
|
28
|
+
*/
|
|
29
|
+
record: StackRecord;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Whether an emission matches a subscription's filter. Reads the record
|
|
33
|
+
* for the fields the envelope deliberately omits, so `entityId` filters on
|
|
34
|
+
* the author and `purged` frames stay filterable without carrying either.
|
|
35
|
+
*/
|
|
36
|
+
export declare function matchesFilter(emitted: EmittedChange, filter?: ChangeFilter): boolean;
|
|
37
|
+
/**
|
|
38
|
+
* The frame a subscriber receives. A `purged` frame never carries the
|
|
39
|
+
* record, whatever was asked for: hard delete is the erasure primitive,
|
|
40
|
+
* and a frame that shipped the body — or the author — of a record the
|
|
41
|
+
* stack has just destroyed would hand every subscriber a permanent copy of
|
|
42
|
+
* the thing being erased. See docs/spec/events.md § Purged records carry
|
|
43
|
+
* nothing.
|
|
44
|
+
*
|
|
45
|
+
* The record rides by reference, shared across every frame projected from
|
|
46
|
+
* one emission: handlers are contractually read-only over it, and copying
|
|
47
|
+
* per subscriber would charge every consumer for a defect none of them
|
|
48
|
+
* have. See docs/spec/events.md § The event shape.
|
|
49
|
+
*/
|
|
50
|
+
export declare function emitted(emission: EmittedChange, includeRecords: boolean): RecordChange;
|
|
51
|
+
/**
|
|
52
|
+
* One subscription's delivery. Subclassed rather than parameterized
|
|
53
|
+
* because the two deliveries differ in kind: an unscoped subscriber is
|
|
54
|
+
* handed the frame inline, while a scoped one has an async permission
|
|
55
|
+
* decision to make first.
|
|
56
|
+
*/
|
|
57
|
+
export declare abstract class Subscription {
|
|
58
|
+
protected readonly handler: (change: RecordChange) => void;
|
|
59
|
+
protected readonly opts: SubscribeOptions;
|
|
60
|
+
private closed;
|
|
61
|
+
constructor(handler: (change: RecordChange) => void, opts: SubscribeOptions);
|
|
62
|
+
/** Called by the emitter for every change, filtered or not. */
|
|
63
|
+
abstract accept(emission: EmittedChange): void;
|
|
64
|
+
get isClosed(): boolean;
|
|
65
|
+
close(): void;
|
|
66
|
+
/**
|
|
67
|
+
* Hand a frame to the handler. A handler that throws cannot fail the
|
|
68
|
+
* write it is being told about — the write is already durable — so the
|
|
69
|
+
* error goes to onError, or is rethrown asynchronously so that it
|
|
70
|
+
* surfaces as an unhandled error rather than vanishing.
|
|
71
|
+
*/
|
|
72
|
+
protected deliver(emission: EmittedChange): void;
|
|
73
|
+
protected reportError(err: unknown): void;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Assemble what the emitter knows about one mutation.
|
|
77
|
+
*
|
|
78
|
+
* The actor is read off the record for every version-bumping op, because
|
|
79
|
+
* `updatedBy`/`updatedVia` were stamped by that same write and so agree
|
|
80
|
+
* with what was persisted by construction. Hard delete stamps nothing and
|
|
81
|
+
* leaves nothing to read, so its actor is the requester, passed in. A
|
|
82
|
+
* purge also drops `parentId` and the create-time `appId`: the frame says
|
|
83
|
+
* that a record of some type was destroyed, and nothing further about
|
|
84
|
+
* whose it was. See docs/spec/events.md § Purged records carry nothing.
|
|
85
|
+
*/
|
|
86
|
+
export declare function buildEmission(op: ChangeOp, record: StackRecord, opts?: {
|
|
87
|
+
actor?: ChangeActor;
|
|
88
|
+
at?: Date;
|
|
89
|
+
}): EmittedChange;
|
|
90
|
+
/**
|
|
91
|
+
* The subscriber registry. One per `Stack`; `ScopedStack` filters the same
|
|
92
|
+
* stream rather than opening its own, so a scoped view can never observe a
|
|
93
|
+
* change the stack did not emit.
|
|
94
|
+
*/
|
|
95
|
+
export declare class ChangeEmitter {
|
|
96
|
+
private readonly subscriptions;
|
|
97
|
+
emit(emission: EmittedChange): void;
|
|
98
|
+
add(subscription: Subscription): Unsubscribe;
|
|
99
|
+
subscribe(handler: (change: RecordChange) => void, opts: SubscribeOptions): Unsubscribe;
|
|
100
|
+
/** Ends every subscription — a closed stack emits nothing further. */
|
|
101
|
+
closeAll(): void;
|
|
102
|
+
}
|
|
103
|
+
/** The kind each op produces. See docs/spec/events.md § The event shape. */
|
|
104
|
+
export declare const CHANGE_KINDS: Record<ChangeOp, ChangeKind>;
|
|
105
|
+
//# sourceMappingURL=changes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"changes.d.ts","sourceRoot":"","sources":["../src/changes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EACV,WAAW,EACX,YAAY,EACZ,UAAU,EACV,QAAQ,EACR,YAAY,EACZ,WAAW,EACX,gBAAgB,EAChB,WAAW,EACZ,MAAM,YAAY,CAAC;AAEpB;;;;GAIG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B,MAAM,EAAE,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;IACrC;;;;OAIG;IACH,MAAM,EAAE,WAAW,CAAC;CACrB,CAAC;AAKF;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,aAAa,EAAE,MAAM,CAAC,EAAE,YAAY,GAAG,OAAO,CAoBpF;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,OAAO,CAAC,QAAQ,EAAE,aAAa,EAAE,cAAc,EAAE,OAAO,GAAG,YAAY,CAItF;AAED;;;;;GAKG;AACH,8BAAsB,YAAY;IAI9B,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,IAAI;IAC1D,SAAS,CAAC,QAAQ,CAAC,IAAI,EAAE,gBAAgB;IAJ3C,OAAO,CAAC,MAAM,CAAS;gBAGF,OAAO,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,IAAI,EACvC,IAAI,EAAE,gBAAgB;IAG3C,+DAA+D;IAC/D,QAAQ,CAAC,MAAM,CAAC,QAAQ,EAAE,aAAa,GAAG,IAAI;IAE9C,IAAI,QAAQ,IAAI,OAAO,CAEtB;IAED,KAAK,IAAI,IAAI;IAIb;;;;;OAKG;IACH,SAAS,CAAC,OAAO,CAAC,QAAQ,EAAE,aAAa,GAAG,IAAI;IAShD,SAAS,CAAC,WAAW,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI;CAc1C;AAaD;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAC3B,EAAE,EAAE,QAAQ,EACZ,MAAM,EAAE,WAAW,EACnB,IAAI,GAAE;IAAE,KAAK,CAAC,EAAE,WAAW,CAAC;IAAC,EAAE,CAAC,EAAE,IAAI,CAAA;CAAO,GAC5C,aAAa,CAgCf;AAiBD;;;;GAIG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA2B;IAEzD,IAAI,CAAC,QAAQ,EAAE,aAAa,GAAG,IAAI;IAQnC,GAAG,CAAC,YAAY,EAAE,YAAY,GAAG,WAAW;IAQ5C,SAAS,CAAC,OAAO,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,IAAI,EAAE,IAAI,EAAE,gBAAgB,GAAG,WAAW;IAIvF,sEAAsE;IACtE,QAAQ,IAAI,IAAI;CAIjB;AAED,4EAA4E;AAC5E,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,QAAQ,EAAE,UAAU,CAWrD,CAAC"}
|
package/dist/changes.js
ADDED
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stack — Change Events
|
|
3
|
+
* -------------------------------------------------------
|
|
4
|
+
* The emitter behind StackClient.subscribe(): a subscriber registry, the
|
|
5
|
+
* filter predicate, and the projection that turns what the emitter knows
|
|
6
|
+
* into what a subscriber is allowed to see.
|
|
7
|
+
*
|
|
8
|
+
* The split between those last two is the point of this module. Emission
|
|
9
|
+
* always carries the record — a permission filter has nothing to decide
|
|
10
|
+
* with otherwise, and on a hard delete there is nothing left to fetch —
|
|
11
|
+
* while the frame handed to a handler is projected from it. So the rule
|
|
12
|
+
* that a purge discloses neither the record nor its provenance is a
|
|
13
|
+
* property of one function here, not a convention every emission site has
|
|
14
|
+
* to remember. See docs/spec/events.md.
|
|
15
|
+
*/
|
|
16
|
+
/** The `baseId@version` split, as grants and query filters read it. */
|
|
17
|
+
const baseIdOf = (typeId) => typeId.split('@')[0];
|
|
18
|
+
/**
|
|
19
|
+
* Whether an emission matches a subscription's filter. Reads the record
|
|
20
|
+
* for the fields the envelope deliberately omits, so `entityId` filters on
|
|
21
|
+
* the author and `purged` frames stay filterable without carrying either.
|
|
22
|
+
*/
|
|
23
|
+
export function matchesFilter(emitted, filter) {
|
|
24
|
+
if (!filter)
|
|
25
|
+
return true;
|
|
26
|
+
const { change, record } = emitted;
|
|
27
|
+
if (filter.kinds && !filter.kinds.includes(change.kind))
|
|
28
|
+
return false;
|
|
29
|
+
if (filter.typeId !== undefined) {
|
|
30
|
+
const wanted = Array.isArray(filter.typeId) ? filter.typeId : [filter.typeId];
|
|
31
|
+
const family = baseIdOf(change.typeId);
|
|
32
|
+
if (!wanted.some((t) => baseIdOf(t) === family))
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
if (filter.parentId !== undefined) {
|
|
36
|
+
const parentId = record.parentId ?? null;
|
|
37
|
+
if (parentId !== filter.parentId)
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
if (filter.entityId !== undefined && record.entityId !== filter.entityId)
|
|
41
|
+
return false;
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* The frame a subscriber receives. A `purged` frame never carries the
|
|
46
|
+
* record, whatever was asked for: hard delete is the erasure primitive,
|
|
47
|
+
* and a frame that shipped the body — or the author — of a record the
|
|
48
|
+
* stack has just destroyed would hand every subscriber a permanent copy of
|
|
49
|
+
* the thing being erased. See docs/spec/events.md § Purged records carry
|
|
50
|
+
* nothing.
|
|
51
|
+
*
|
|
52
|
+
* The record rides by reference, shared across every frame projected from
|
|
53
|
+
* one emission: handlers are contractually read-only over it, and copying
|
|
54
|
+
* per subscriber would charge every consumer for a defect none of them
|
|
55
|
+
* have. See docs/spec/events.md § The event shape.
|
|
56
|
+
*/
|
|
57
|
+
export function emitted(emission, includeRecords) {
|
|
58
|
+
const { change, record } = emission;
|
|
59
|
+
if (change.kind === 'purged' || !includeRecords)
|
|
60
|
+
return { ...change };
|
|
61
|
+
return { ...change, record };
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* One subscription's delivery. Subclassed rather than parameterized
|
|
65
|
+
* because the two deliveries differ in kind: an unscoped subscriber is
|
|
66
|
+
* handed the frame inline, while a scoped one has an async permission
|
|
67
|
+
* decision to make first.
|
|
68
|
+
*/
|
|
69
|
+
export class Subscription {
|
|
70
|
+
handler;
|
|
71
|
+
opts;
|
|
72
|
+
closed = false;
|
|
73
|
+
constructor(handler, opts) {
|
|
74
|
+
this.handler = handler;
|
|
75
|
+
this.opts = opts;
|
|
76
|
+
}
|
|
77
|
+
get isClosed() {
|
|
78
|
+
return this.closed;
|
|
79
|
+
}
|
|
80
|
+
close() {
|
|
81
|
+
this.closed = true;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Hand a frame to the handler. A handler that throws cannot fail the
|
|
85
|
+
* write it is being told about — the write is already durable — so the
|
|
86
|
+
* error goes to onError, or is rethrown asynchronously so that it
|
|
87
|
+
* surfaces as an unhandled error rather than vanishing.
|
|
88
|
+
*/
|
|
89
|
+
deliver(emission) {
|
|
90
|
+
if (this.closed)
|
|
91
|
+
return;
|
|
92
|
+
try {
|
|
93
|
+
this.handler(emitted(emission, this.opts.includeRecords === true));
|
|
94
|
+
}
|
|
95
|
+
catch (err) {
|
|
96
|
+
this.reportError(err);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
reportError(err) {
|
|
100
|
+
if (this.opts.onError) {
|
|
101
|
+
try {
|
|
102
|
+
this.opts.onError(err);
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
// An onError that throws has nowhere left to report to. Losing it
|
|
106
|
+
// is better than letting it escape into a mutation's call stack.
|
|
107
|
+
}
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
queueMicrotask(() => {
|
|
111
|
+
throw err;
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Delivery with no permission boundary: `Stack` is the unscoped layer, so
|
|
117
|
+
* a subscriber there already reaches every record by other means.
|
|
118
|
+
*/
|
|
119
|
+
class UnscopedSubscription extends Subscription {
|
|
120
|
+
accept(emission) {
|
|
121
|
+
if (!matchesFilter(emission, this.opts.filter))
|
|
122
|
+
return;
|
|
123
|
+
this.deliver(emission);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Assemble what the emitter knows about one mutation.
|
|
128
|
+
*
|
|
129
|
+
* The actor is read off the record for every version-bumping op, because
|
|
130
|
+
* `updatedBy`/`updatedVia` were stamped by that same write and so agree
|
|
131
|
+
* with what was persisted by construction. Hard delete stamps nothing and
|
|
132
|
+
* leaves nothing to read, so its actor is the requester, passed in. A
|
|
133
|
+
* purge also drops `parentId` and the create-time `appId`: the frame says
|
|
134
|
+
* that a record of some type was destroyed, and nothing further about
|
|
135
|
+
* whose it was. See docs/spec/events.md § Purged records carry nothing.
|
|
136
|
+
*/
|
|
137
|
+
export function buildEmission(op, record, opts = {}) {
|
|
138
|
+
const kind = CHANGE_KINDS[op];
|
|
139
|
+
if (kind === 'purged') {
|
|
140
|
+
return {
|
|
141
|
+
record,
|
|
142
|
+
change: {
|
|
143
|
+
kind,
|
|
144
|
+
op,
|
|
145
|
+
recordId: record.id,
|
|
146
|
+
typeId: record.typeId,
|
|
147
|
+
version: record.version,
|
|
148
|
+
updatedAt: opts.at ?? new Date(),
|
|
149
|
+
...(opts.actor && { actor: opts.actor }),
|
|
150
|
+
},
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
const actor = actorOf(record, kind);
|
|
154
|
+
return {
|
|
155
|
+
record,
|
|
156
|
+
change: {
|
|
157
|
+
kind,
|
|
158
|
+
op,
|
|
159
|
+
recordId: record.id,
|
|
160
|
+
typeId: record.typeId,
|
|
161
|
+
version: record.version,
|
|
162
|
+
updatedAt: record.updatedAt,
|
|
163
|
+
...(record.parentId !== undefined && { parentId: record.parentId }),
|
|
164
|
+
...(actor && { actor }),
|
|
165
|
+
},
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* The acting identity a stored record reports. `appId` rides along only on
|
|
170
|
+
* a create, the one mutation where the record's app and the acting app are
|
|
171
|
+
* the same fact — on any later version it is the *creating* app, which
|
|
172
|
+
* describes the record rather than the change.
|
|
173
|
+
*/
|
|
174
|
+
function actorOf(record, kind) {
|
|
175
|
+
if (!record.updatedBy)
|
|
176
|
+
return undefined;
|
|
177
|
+
return {
|
|
178
|
+
entityId: record.updatedBy,
|
|
179
|
+
...(record.updatedVia !== undefined && { principalId: record.updatedVia }),
|
|
180
|
+
...(kind === 'created' && record.appId !== undefined && { appId: record.appId }),
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* The subscriber registry. One per `Stack`; `ScopedStack` filters the same
|
|
185
|
+
* stream rather than opening its own, so a scoped view can never observe a
|
|
186
|
+
* change the stack did not emit.
|
|
187
|
+
*/
|
|
188
|
+
export class ChangeEmitter {
|
|
189
|
+
subscriptions = new Set();
|
|
190
|
+
emit(emission) {
|
|
191
|
+
// Snapshotted: a handler may subscribe or unsubscribe while this loop
|
|
192
|
+
// runs, and neither should be seen by the emission already in flight.
|
|
193
|
+
for (const subscription of [...this.subscriptions]) {
|
|
194
|
+
if (!subscription.isClosed)
|
|
195
|
+
subscription.accept(emission);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
add(subscription) {
|
|
199
|
+
this.subscriptions.add(subscription);
|
|
200
|
+
return () => {
|
|
201
|
+
subscription.close();
|
|
202
|
+
this.subscriptions.delete(subscription);
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
subscribe(handler, opts) {
|
|
206
|
+
return this.add(new UnscopedSubscription(handler, opts));
|
|
207
|
+
}
|
|
208
|
+
/** Ends every subscription — a closed stack emits nothing further. */
|
|
209
|
+
closeAll() {
|
|
210
|
+
for (const subscription of this.subscriptions)
|
|
211
|
+
subscription.close();
|
|
212
|
+
this.subscriptions.clear();
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
/** The kind each op produces. See docs/spec/events.md § The event shape. */
|
|
216
|
+
export const CHANGE_KINDS = {
|
|
217
|
+
create: 'created',
|
|
218
|
+
update: 'changed',
|
|
219
|
+
associate: 'changed',
|
|
220
|
+
dissociate: 'changed',
|
|
221
|
+
permissions: 'changed',
|
|
222
|
+
migrate: 'changed',
|
|
223
|
+
restore: 'changed',
|
|
224
|
+
undelete: 'changed',
|
|
225
|
+
delete: 'deleted',
|
|
226
|
+
'hard-delete': 'purged',
|
|
227
|
+
};
|
|
228
|
+
//# sourceMappingURL=changes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"changes.js","sourceRoot":"","sources":["../src/changes.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
*/
|
|
17
17
|
export { Stack, ScopedStack, StackError, StackValidationError, StackMigrationError, StackPermissionError, StackNotFoundError, StackConflictError, StackVersionConflictError, StackQueryError, StackSchemaDriftError, StackPayloadTooLargeError, StackTimeoutError, StackClosedError, } from './stack.js';
|
|
18
18
|
export type { StackErrorCode, StackClient, CreateRecordOptions, StackOptions, GetRecordOptions, DeleteRecordOptions, IfVersionOptions, CollectAttachmentGarbageOptions, CollectAttachmentGarbageResult, } from './stack.js';
|
|
19
|
-
export type { RecordId, TypeId, FileId, EntityId, AttachmentContent, StackRecord, RecordVersion, StackType, TypeSchema, FieldDef, ScalarFieldDef, ArrayFieldDef, ObjectFieldDef, ScalarFieldKind, Association, TagAssociation, AttachmentAssociation, RelationshipAssociation, Permission, StackQuery, RecordFilter, QuerySort, QueryResult, DateRange, Migration, MigrationFn, StackAdapter, StackFeatures, TokenSession, EntityContent, AppContent, GroupContent, GrantAction, GrantContent, ConfigContent, } from './types.js';
|
|
19
|
+
export type { RecordId, TypeId, FileId, EntityId, AttachmentContent, StackRecord, RecordVersion, ActorOptions, ChangeKind, ChangeOp, ChangeActor, RecordChange, ChangeFilter, SubscribeOptions, Unsubscribe, ExpectedVersionOptions, SnapshotOptions, StackType, TypeSchema, FieldDef, ScalarFieldDef, ArrayFieldDef, ObjectFieldDef, ScalarFieldKind, Association, TagAssociation, AttachmentAssociation, RelationshipAssociation, Permission, StackQuery, RecordFilter, QuerySort, QueryResult, DateRange, Migration, MigrationFn, StackAdapter, StackFeatures, TokenSession, EntityContent, AppContent, GroupContent, GrantAction, GrantContent, ConfigContent, } from './types.js';
|
|
20
20
|
export { SYSTEM_TYPES } from './types.js';
|
|
21
21
|
export { generateId } from './id.js';
|
|
22
22
|
export { hashSchema, isCompatible } from './schema.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,EACL,KAAK,EACL,WAAW,EACX,UAAU,EACV,oBAAoB,EACpB,mBAAmB,EACnB,oBAAoB,EACpB,kBAAkB,EAClB,kBAAkB,EAClB,yBAAyB,EACzB,eAAe,EACf,qBAAqB,EACrB,yBAAyB,EACzB,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,cAAc,EACd,WAAW,EACX,mBAAmB,EACnB,YAAY,EACZ,gBAAgB,EAChB,mBAAmB,EACnB,gBAAgB,EAChB,+BAA+B,EAC/B,8BAA8B,GAC/B,MAAM,YAAY,CAAC;AAGpB,YAAY,EACV,QAAQ,EACR,MAAM,EACN,MAAM,EACN,QAAQ,EACR,iBAAiB,EACjB,WAAW,EACX,aAAa,EACb,SAAS,EACT,UAAU,EACV,QAAQ,EACR,cAAc,EACd,aAAa,EACb,cAAc,EACd,eAAe,EACf,WAAW,EACX,cAAc,EACd,qBAAqB,EACrB,uBAAuB,EACvB,UAAU,EACV,UAAU,EACV,YAAY,EACZ,SAAS,EACT,WAAW,EACX,SAAS,EACT,SAAS,EACT,WAAW,EACX,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,aAAa,EACb,UAAU,EACV,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,aAAa,GACd,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAM1C,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACvD,YAAY,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACxD,YAAY,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,EACL,KAAK,EACL,WAAW,EACX,UAAU,EACV,oBAAoB,EACpB,mBAAmB,EACnB,oBAAoB,EACpB,kBAAkB,EAClB,kBAAkB,EAClB,yBAAyB,EACzB,eAAe,EACf,qBAAqB,EACrB,yBAAyB,EACzB,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,cAAc,EACd,WAAW,EACX,mBAAmB,EACnB,YAAY,EACZ,gBAAgB,EAChB,mBAAmB,EACnB,gBAAgB,EAChB,+BAA+B,EAC/B,8BAA8B,GAC/B,MAAM,YAAY,CAAC;AAGpB,YAAY,EACV,QAAQ,EACR,MAAM,EACN,MAAM,EACN,QAAQ,EACR,iBAAiB,EACjB,WAAW,EACX,aAAa,EACb,YAAY,EACZ,UAAU,EACV,QAAQ,EACR,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,gBAAgB,EAChB,WAAW,EACX,sBAAsB,EACtB,eAAe,EACf,SAAS,EACT,UAAU,EACV,QAAQ,EACR,cAAc,EACd,aAAa,EACb,cAAc,EACd,eAAe,EACf,WAAW,EACX,cAAc,EACd,qBAAqB,EACrB,uBAAuB,EACvB,UAAU,EACV,UAAU,EACV,YAAY,EACZ,SAAS,EACT,WAAW,EACX,SAAS,EACT,SAAS,EACT,WAAW,EACX,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,aAAa,EACb,UAAU,EACV,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,aAAa,GACd,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAM1C,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACvD,YAAY,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACxD,YAAY,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,kCAAkC;AAClC,OAAO,EACL,KAAK,EACL,WAAW,EACX,UAAU,EACV,oBAAoB,EACpB,mBAAmB,EACnB,oBAAoB,EACpB,kBAAkB,EAClB,kBAAkB,EAClB,yBAAyB,EACzB,eAAe,EACf,qBAAqB,EACrB,yBAAyB,EACzB,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,kCAAkC;AAClC,OAAO,EACL,KAAK,EACL,WAAW,EACX,UAAU,EACV,oBAAoB,EACpB,mBAAmB,EACnB,oBAAoB,EACpB,kBAAkB,EAClB,kBAAkB,EAClB,yBAAyB,EACzB,eAAe,EACf,qBAAqB,EACrB,yBAAyB,EACzB,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,YAAY,CAAC;AA8DpB,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,YAAY;AAEZ,4EAA4E;AAC5E,sEAAsE;AACtE,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAGvD,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC"}
|