@haverstack/core 0.44.0 → 0.45.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.
Files changed (43) hide show
  1. package/README.md +1 -1
  2. package/dist/adapter/blobs.d.ts +18 -0
  3. package/dist/adapter/blobs.d.ts.map +1 -0
  4. package/dist/adapter/blobs.js +27 -0
  5. package/dist/adapter/blobs.js.map +1 -0
  6. package/dist/adapter/combine.d.ts.map +1 -1
  7. package/dist/adapter/combine.js +13 -5
  8. package/dist/adapter/combine.js.map +1 -1
  9. package/dist/adapter/copy.d.ts +7 -3
  10. package/dist/adapter/copy.d.ts.map +1 -1
  11. package/dist/adapter/copy.js +41 -15
  12. package/dist/adapter/copy.js.map +1 -1
  13. package/dist/adapter/head.d.ts +38 -0
  14. package/dist/adapter/head.d.ts.map +1 -0
  15. package/dist/adapter/head.js +85 -0
  16. package/dist/adapter/head.js.map +1 -0
  17. package/dist/adapter/index.d.ts +5 -1
  18. package/dist/adapter/index.d.ts.map +1 -1
  19. package/dist/adapter/index.js +3 -0
  20. package/dist/adapter/index.js.map +1 -1
  21. package/dist/stack/stack.d.ts +3 -3
  22. package/dist/stack/stack.d.ts.map +1 -1
  23. package/dist/stack/stack.js +13 -6
  24. package/dist/stack/stack.js.map +1 -1
  25. package/dist/testing.d.ts +6 -2
  26. package/dist/testing.d.ts.map +1 -1
  27. package/dist/testing.js +14 -11
  28. package/dist/testing.js.map +1 -1
  29. package/dist/types/adapter.d.ts +48 -5
  30. package/dist/types/adapter.d.ts.map +1 -1
  31. package/dist/validate.d.ts +2 -0
  32. package/dist/validate.d.ts.map +1 -1
  33. package/dist/validate.js +2 -2
  34. package/dist/validate.js.map +1 -1
  35. package/dist/wire/index.d.ts +1 -1
  36. package/dist/wire/index.d.ts.map +1 -1
  37. package/dist/wire/index.js +1 -1
  38. package/dist/wire/index.js.map +1 -1
  39. package/dist/wire/request.d.ts +8 -1
  40. package/dist/wire/request.d.ts.map +1 -1
  41. package/dist/wire/request.js +20 -0
  42. package/dist/wire/request.js.map +1 -1
  43. package/package.json +1 -1
package/README.md CHANGED
@@ -203,7 +203,7 @@ export const manifest: AppManifest = {
203
203
 
204
204
  **When the owner runs the app**, it opens with `Stack.open(adapter, { migrations })`, calls `install(stack)`, then `new Library(stack)`. A server hands each requester `new Library(stack.asActor(session))`.
205
205
 
206
- **When the app runs elsewhere** — holding its own key and reaching the stack through `APIAdapter` — it can't define types, so it asks: `adapter.requestInstall(manifest)` resolves to `pending` until the owner approves. The owner reviews `stack.planInstall(manifest, { did })` and applies it with `stack.installApp(manifest, { did, fingerprint: plan.fingerprint })`, which defines the types, registers the app's key and grants it the requests. The app still opens with its `migrations`, then builds `new Library(stack)` over its own connection. See [App installs](https://github.com/haverstack/core/blob/main/docs/spec/apps.md).
206
+ **When the app runs elsewhere** — holding its own key and reaching the stack through `APIAdapter` — it can't define types, so it asks: `adapter.requestInstall(manifest)`, present when the server advertises install requests, resolves to `pending` until the owner approves. The owner reviews `stack.planInstall(manifest, { did })` and applies it with `stack.installApp(manifest, { did, fingerprint: plan.fingerprint })`, which defines the types, registers the app's key and grants it the requests. The app still opens with its `migrations`, then builds `new Library(stack)` over its own connection. See [App installs](https://github.com/haverstack/core/blob/main/docs/spec/apps.md).
207
207
 
208
208
  **Name content with an interface**, as above. `ContentOf` flattens its result, so a `type` alias shows the expanded object in editor hovers, while an interface keeps its name. typescript-eslint's recommended `no-empty-object-type` rule rejects an empty interface; its `allowInterfaces: 'with-single-extends'` option admits this one.
209
209
 
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Blob listing windows and file ids
3
+ * -------------------------------------------------------
4
+ * `listBlobs()` reads in `fileId` order and pages forward from
5
+ * `afterFileId`, on every adapter. An adapter whose storage hands back an
6
+ * unordered set of names windows it here, so the order and the cursor mean
7
+ * the same thing whatever stores the bytes. See docs/spec/data-model.md
8
+ * § List order.
9
+ */
10
+ import type { BlobsQuery, FileId } from '../types/index.js';
11
+ /** The `fileId`s a `listBlobs(query)` answers with, out of every one stored. */
12
+ export declare function blobWindow(fileIds: Iterable<FileId>, query?: BlobsQuery): FileId[];
13
+ /**
14
+ * Refuses a name no blob could have, before a store or a page is asked for
15
+ * it. `label` names where it arrived, such as a request's `afterFileId`.
16
+ */
17
+ export declare function assertFileId(fileId: string, label?: string): void;
18
+ //# sourceMappingURL=blobs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blobs.d.ts","sourceRoot":"","sources":["../../src/adapter/blobs.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAG5D,gFAAgF;AAChF,wBAAgB,UAAU,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,KAAK,GAAE,UAAe,GAAG,MAAM,EAAE,CAItF;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,SAAW,GAAG,IAAI,CAInE"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Blob listing windows and file ids
3
+ * -------------------------------------------------------
4
+ * `listBlobs()` reads in `fileId` order and pages forward from
5
+ * `afterFileId`, on every adapter. An adapter whose storage hands back an
6
+ * unordered set of names windows it here, so the order and the cursor mean
7
+ * the same thing whatever stores the bytes. See docs/spec/data-model.md
8
+ * § List order.
9
+ */
10
+ import { StackBadRequestError } from '../errors.js';
11
+ import { FILE_ID_RE } from '../validate.js';
12
+ /** The `fileId`s a `listBlobs(query)` answers with, out of every one stored. */
13
+ export function blobWindow(fileIds, query = {}) {
14
+ const { afterFileId, limit } = query;
15
+ const after = [...fileIds].filter((id) => afterFileId === undefined || id > afterFileId).sort();
16
+ return limit === undefined ? after : after.slice(0, limit);
17
+ }
18
+ /**
19
+ * Refuses a name no blob could have, before a store or a page is asked for
20
+ * it. `label` names where it arrived, such as a request's `afterFileId`.
21
+ */
22
+ export function assertFileId(fileId, label = 'fileId') {
23
+ if (!FILE_ID_RE.test(fileId)) {
24
+ throw new StackBadRequestError(`Invalid ${label}: expected 64-character lowercase hex string`);
25
+ }
26
+ }
27
+ //# sourceMappingURL=blobs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blobs.js","sourceRoot":"","sources":["../../src/adapter/blobs.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAEpD,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAE5C,gFAAgF;AAChF,MAAM,UAAU,UAAU,CAAC,OAAyB,EAAE,QAAoB,EAAE;IAC1E,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,GAAG,KAAK,CAAC;IACrC,MAAM,KAAK,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,WAAW,KAAK,SAAS,IAAI,EAAE,GAAG,WAAW,CAAC,CAAC,IAAI,EAAE,CAAC;IAChG,OAAO,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;AAC7D,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,MAAc,EAAE,KAAK,GAAG,QAAQ;IAC3D,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,oBAAoB,CAAC,WAAW,KAAK,8CAA8C,CAAC,CAAC;IACjG,CAAC;AACH,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"combine.d.ts","sourceRoot":"","sources":["../../src/adapter/combine.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAKV,YAAY,EACZ,kBAAkB,EAClB,gBAAgB,EAGjB,MAAM,mBAAmB,CAAC;AAE3B;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE;IACrC,MAAM,EAAE,kBAAkB,CAAC;IAC3B,IAAI,EAAE,gBAAgB,CAAC;CACxB,GAAG,YAAY,CA8Ef"}
1
+ {"version":3,"file":"combine.d.ts","sourceRoot":"","sources":["../../src/adapter/combine.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAKV,YAAY,EACZ,kBAAkB,EAClB,gBAAgB,EAGjB,MAAM,mBAAmB,CAAC;AAG3B;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE;IACrC,MAAM,EAAE,kBAAkB,CAAC;IAC3B,IAAI,EAAE,gBAAgB,CAAC;CACxB,GAAG,YAAY,CAqFf"}
@@ -5,6 +5,7 @@
5
5
  * deployment can keep records and bytes in different backends without
6
6
  * either adapter knowing about the other.
7
7
  */
8
+ import { combinedHead } from './head.js';
8
9
  /**
9
10
  * Compose a StackRecordAdapter and a StackBlobAdapter into a single StackAdapter.
10
11
  * Use this when you want different backends for records and blobs, e.g.:
@@ -20,6 +21,10 @@ export function combineAdapters(parts) {
20
21
  get ownerEntityId() {
21
22
  return parts.record.ownerEntityId;
22
23
  },
24
+ // The record half's, since writers names who writes the Records.
25
+ get writers() {
26
+ return parts.record.writers;
27
+ },
23
28
  createRecord: (r, opts) => parts.record.createRecord(r, opts),
24
29
  getRecord: (id) => parts.record.getRecord(id),
25
30
  patchContent: (id, patch, opts) => parts.record.patchContent(id, patch, opts),
@@ -52,10 +57,8 @@ export function combineAdapters(parts) {
52
57
  ...(parts.record.queryReadable && {
53
58
  queryReadable: (q, reach) => parts.record.queryReadable(q, reach),
54
59
  }),
55
- // Forwarded on the same terms, and it decides more than it looks:
56
- // Stack.relaysChanges reads its presence, so dropping it here would
57
- // leave a combined stack quietly emitting only its own writes while a
58
- // remote record backend's feed went unread.
60
+ // Forwarded on the same terms: dropping it would leave a shared record
61
+ // backend's feed unread, and Stack would refuse to subscribe at all.
59
62
  ...(parts.record.subscribeChanges && {
60
63
  subscribeChanges: (opts, handler) => parts.record.subscribeChanges(opts, handler),
61
64
  }),
@@ -67,7 +70,12 @@ export function combineAdapters(parts) {
67
70
  getBlob: (id) => parts.blob.getBlob(id),
68
71
  deleteBlob: (id) => parts.blob.deleteBlob(id),
69
72
  ...(parts.blob.listBlobs && {
70
- listBlobs: () => parts.blob.listBlobs(),
73
+ listBlobs: (query) => parts.blob.listBlobs(query),
74
+ }),
75
+ // One head for the whole store, so a write to either half moves it.
76
+ ...(parts.record.head &&
77
+ parts.blob.head && {
78
+ head: async () => combinedHead(await parts.record.head(), await parts.blob.head()),
71
79
  }),
72
80
  async flush() {
73
81
  await parts.record.flush?.();
@@ -1 +1 @@
1
- {"version":3,"file":"combine.js","sourceRoot":"","sources":["../../src/adapter/combine.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"combine.js","sourceRoot":"","sources":["../../src/adapter/combine.ts"],"names":[],"mappings":"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"}
@@ -10,7 +10,11 @@
10
10
  * between storage engines are all this one call, with a different source
11
11
  * and a different kind of store to create. Full trust, like any direct
12
12
  * adapter access: authorship and history land as recorded, which no write
13
- * through Stack may do. See docs/spec/portability.md.
13
+ * through Stack may do.
14
+ *
15
+ * A copy reads one moment of its source: it reads the source's head before
16
+ * and after, and refuses the copy if the two differ. One rule for every
17
+ * source, whoever else writes to it. See docs/spec/portability.md.
14
18
  */
15
19
  import type { StackAdapter, StoreSeed } from '../types/index.js';
16
20
  /** Creates a new store from `seed`: `LocalAdapter.open({ path, seed })`, say. */
@@ -19,8 +23,8 @@ export type CreateStore = (seed: StoreSeed) => Promise<StackAdapter> | StackAdap
19
23
  * Copy everything `from` holds into the store `create` makes from its
20
24
  * `_config` record and that record's history, and return that store, open.
21
25
  * Not atomic: a failure closes the store part-written, and the caller, whose
22
- * store it is, removes it. The source must not be written meanwhile; nothing
23
- * here can check that.
26
+ * store it is, removes it. A source written meanwhile is refused with
27
+ * StackConflictError, and the copy is run again into a new store.
24
28
  * See docs/spec/portability.md § Copying a stack.
25
29
  */
26
30
  export declare function copyStack(from: StackAdapter, create: CreateStore): Promise<StackAdapter>;
@@ -1 +1 @@
1
- {"version":3,"file":"copy.d.ts","sourceRoot":"","sources":["../../src/adapter/copy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH,OAAO,KAAK,EAGV,YAAY,EAEZ,SAAS,EACV,MAAM,mBAAmB,CAAC;AAG3B,iFAAiF;AACjF,MAAM,MAAM,WAAW,GAAG,CAAC,IAAI,EAAE,SAAS,KAAK,OAAO,CAAC,YAAY,CAAC,GAAG,YAAY,CAAC;AAYpF;;;;;;;GAOG;AACH,wBAAsB,SAAS,CAAC,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CAgC9F"}
1
+ {"version":3,"file":"copy.d.ts","sourceRoot":"","sources":["../../src/adapter/copy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAIH,OAAO,KAAK,EAIV,YAAY,EAEZ,SAAS,EACV,MAAM,mBAAmB,CAAC;AAG3B,iFAAiF;AACjF,MAAM,MAAM,WAAW,GAAG,CAAC,IAAI,EAAE,SAAS,KAAK,OAAO,CAAC,YAAY,CAAC,GAAG,YAAY,CAAC;AAYpF;;;;;;;GAOG;AACH,wBAAsB,SAAS,CAAC,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CAoC9F"}
@@ -10,9 +10,13 @@
10
10
  * between storage engines are all this one call, with a different source
11
11
  * and a different kind of store to create. Full trust, like any direct
12
12
  * adapter access: authorship and history land as recorded, which no write
13
- * through Stack may do. See docs/spec/portability.md.
13
+ * through Stack may do.
14
+ *
15
+ * A copy reads one moment of its source: it reads the source's head before
16
+ * and after, and refuses the copy if the two differ. One rule for every
17
+ * source, whoever else writes to it. See docs/spec/portability.md.
14
18
  */
15
- import { InvalidAdapterError, OwnerMismatchError } from '../errors.js';
19
+ import { InvalidAdapterError, OwnerMismatchError, StackConflictError } from '../errors.js';
16
20
  import { resolveQuery } from '../query-validation.js';
17
21
  import { SYSTEM_TYPES } from '../types/index.js';
18
22
  /** Records read per page; any size works, as each page is written before the next is read. */
@@ -27,19 +31,22 @@ const EVERYTHING = {
27
31
  * Copy everything `from` holds into the store `create` makes from its
28
32
  * `_config` record and that record's history, and return that store, open.
29
33
  * Not atomic: a failure closes the store part-written, and the caller, whose
30
- * store it is, removes it. The source must not be written meanwhile; nothing
31
- * here can check that.
34
+ * store it is, removes it. A source written meanwhile is refused with
35
+ * StackConflictError, and the copy is run again into a new store.
32
36
  * See docs/spec/portability.md § Copying a stack.
33
37
  */
34
38
  export async function copyStack(from, create) {
35
39
  const listBlobs = from.listBlobs?.bind(from);
36
- if (!listBlobs) {
37
- throw new InvalidAdapterError('Cannot copy from this adapter: it has no listBlobs(), so its blobs cannot be enumerated.');
38
- }
40
+ if (!listBlobs)
41
+ refuseSource('it has no listBlobs(), so its blobs cannot be enumerated');
42
+ const head = from.head?.bind(from);
43
+ if (!head)
44
+ refuseSource('it has no head(), so a write during the copy could not be detected');
45
+ // Before the first read, so every write that could land during one moves it.
46
+ const started = await head();
39
47
  const config = await from.getRecord(SYSTEM_TYPES.CONFIG);
40
- if (!config) {
41
- throw new InvalidAdapterError('Cannot copy from this adapter: it holds no _config record.');
42
- }
48
+ if (!config)
49
+ refuseSource('it holds no _config record');
43
50
  const [versions, journal] = await Promise.all([
44
51
  from.getVersions(config.id),
45
52
  from.getJournal(config.id),
@@ -52,13 +59,17 @@ export async function copyStack(from, create) {
52
59
  const listHeld = to.listBlobs?.bind(to);
53
60
  if (!listHeld)
54
61
  refuseTarget('it has no listBlobs(), so it could not be copied from in turn');
62
+ if (!to.head)
63
+ refuseTarget('it has no head(), so it could not be copied from in turn');
55
64
  await assertNewStore(to, config.content.ownerEntityId, listHeld);
56
65
  for (const type of await from.listTypes())
57
66
  await to.saveType(type);
58
67
  // Bytes before the Records that name them, as every upload writes them.
59
- for (const { fileId } of await listBlobs())
60
- await to.putBlob(await from.getBlob(fileId));
68
+ await copyBlobs(from, to, listBlobs);
61
69
  await copyRecords(from, importRecord);
70
+ if ((await head()) !== started) {
71
+ throw new StackConflictError('The source was written while it was copied. Copy it again into a new store.');
72
+ }
62
73
  return to;
63
74
  }
64
75
  catch (err) {
@@ -67,14 +78,17 @@ export async function copyStack(from, create) {
67
78
  throw err;
68
79
  }
69
80
  }
81
+ function refuseSource(why) {
82
+ throw new InvalidAdapterError(`Cannot copy from this adapter: ${why}.`);
83
+ }
70
84
  function refuseTarget(why) {
71
85
  throw new InvalidAdapterError(`Cannot copy into the store create() returned: ${why}.`);
72
86
  }
73
87
  /**
74
88
  * A target is a store as its adapter creates one: the source's owner,
75
89
  * checked as open() checks it, and nothing held yet — no Record, no Type, no
76
- * blob. Every end of a copy lists all it holds, so a target is itself a
77
- * store a later copy can read in full.
90
+ * blob. Every end of a copy lists all it holds and has a head, so a target
91
+ * is itself a store a later copy can read.
78
92
  */
79
93
  async function assertNewStore(to, ownerEntityId, listHeld) {
80
94
  if (to.ownerEntityId !== ownerEntityId) {
@@ -85,14 +99,26 @@ async function assertNewStore(to, ownerEntityId, listHeld) {
85
99
  }
86
100
  if ((await to.listTypes()).length)
87
101
  refuseTarget('it already holds Types');
88
- if ((await listHeld()).length)
102
+ if ((await listHeld({ limit: 1 })).length)
89
103
  refuseTarget('it already holds blobs');
90
104
  }
105
+ async function copyBlobs(from, to, listBlobs) {
106
+ let afterFileId;
107
+ for (;;) {
108
+ const page = await listBlobs({ afterFileId, limit: PAGE_SIZE });
109
+ for (const { fileId } of page)
110
+ await to.putBlob(await from.getBlob(fileId));
111
+ if (page.length < PAGE_SIZE)
112
+ return;
113
+ afterFileId = page[page.length - 1].fileId;
114
+ }
115
+ }
91
116
  async function copyRecords(from, importRecord) {
92
117
  let cursor;
93
118
  do {
94
119
  const page = await from.queryRecords(resolveQuery({ ...EVERYTHING, cursor }));
95
120
  for (const record of page.records) {
121
+ // One Record's history is read whole, as importRecord() takes it.
96
122
  const [versions, journal] = await Promise.all([
97
123
  from.getVersions(record.id),
98
124
  from.getJournal(record.id),
@@ -1 +1 @@
1
- {"version":3,"file":"copy.js","sourceRoot":"","sources":["../../src/adapter/copy.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"copy.js","sourceRoot":"","sources":["../../src/adapter/copy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Write heads
3
+ * -------------------------------------------------------
4
+ * A head says where a store's writes stand, so a reader that takes one
5
+ * before and one after learns whether anything was written between. A
6
+ * local store's writer is the process that owns it, so that process can
7
+ * count its own writes: trackWrites() wraps every write method an adapter
8
+ * has, so no method has to remember to. The count starts in a random
9
+ * epoch, so a store reopened (or a server restarted) never returns to a
10
+ * head it reported before. See docs/spec/portability.md § Copying a stack.
11
+ */
12
+ /** One store's writes, counted for its `head()`. */
13
+ declare class WriteHead {
14
+ private readonly epoch;
15
+ private settled;
16
+ private inFlight;
17
+ private busyReads;
18
+ /**
19
+ * A write in flight may land on either side of a read, so a head read
20
+ * meanwhile matches no other head; one read after it settles differs from
21
+ * every head read before.
22
+ */
23
+ read(): string;
24
+ track<T>(write: () => Promise<T>): Promise<T>;
25
+ }
26
+ /** The head a `head()` reports. */
27
+ export type { WriteHead };
28
+ /**
29
+ * Wrap every write method `adapter` has so it moves the returned head, and
30
+ * return that head for the adapter's `head()` to read. Call once, from the
31
+ * adapter's own constructor: it wraps the methods present then, so a write
32
+ * method assigned as a field after that call goes uncounted (the
33
+ * conformance suite's head tests catch one).
34
+ */
35
+ export declare function trackWrites(adapter: object): WriteHead;
36
+ /** The head of a store made of two halves: it moves when either does. */
37
+ export declare function combinedHead(record: string, blob: string): string;
38
+ //# sourceMappingURL=head.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"head.d.ts","sourceRoot":"","sources":["../../src/adapter/head.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AA6BH,oDAAoD;AACpD,cAAM,SAAS;IACb,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAuB;IAC7C,OAAO,CAAC,OAAO,CAAK;IACpB,OAAO,CAAC,QAAQ,CAAK;IACrB,OAAO,CAAC,SAAS,CAAK;IAEtB;;;;OAIG;IACH,IAAI,IAAI,MAAM;IAKR,KAAK,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;CASpD;AAED,mCAAmC;AACnC,YAAY,EAAE,SAAS,EAAE,CAAC;AAE1B;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CAUtD;AAED,yEAAyE;AACzE,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAEjE"}
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Write heads
3
+ * -------------------------------------------------------
4
+ * A head says where a store's writes stand, so a reader that takes one
5
+ * before and one after learns whether anything was written between. A
6
+ * local store's writer is the process that owns it, so that process can
7
+ * count its own writes: trackWrites() wraps every write method an adapter
8
+ * has, so no method has to remember to. The count starts in a random
9
+ * epoch, so a store reopened (or a server restarted) never returns to a
10
+ * head it reported before. See docs/spec/portability.md § Copying a stack.
11
+ */
12
+ /**
13
+ * Every write method, keyed so a method added to StackAdapter fails
14
+ * typecheck here until it is listed or named a read.
15
+ */
16
+ const WRITE_METHODS = {
17
+ createRecord: true,
18
+ importRecord: true,
19
+ patchContent: true,
20
+ deleteRecord: true,
21
+ undeleteRecord: true,
22
+ setParent: true,
23
+ setUnlisted: true,
24
+ editAssociations: true,
25
+ setAssociations: true,
26
+ editAccess: true,
27
+ setAccess: true,
28
+ restoreVersion: true,
29
+ commitMigration: true,
30
+ saveType: true,
31
+ deleteUnreferencedAttachmentRecords: true,
32
+ putBlob: true,
33
+ deleteBlob: true,
34
+ putAttachmentWithMetadata: true,
35
+ };
36
+ /** One store's writes, counted for its `head()`. */
37
+ class WriteHead {
38
+ epoch = crypto.randomUUID();
39
+ settled = 0;
40
+ inFlight = 0;
41
+ busyReads = 0;
42
+ /**
43
+ * A write in flight may land on either side of a read, so a head read
44
+ * meanwhile matches no other head; one read after it settles differs from
45
+ * every head read before.
46
+ */
47
+ read() {
48
+ if (this.inFlight)
49
+ return `${this.epoch}.${this.settled}.${++this.busyReads}`;
50
+ return `${this.epoch}.${this.settled}`;
51
+ }
52
+ async track(write) {
53
+ this.inFlight++;
54
+ try {
55
+ return await write();
56
+ }
57
+ finally {
58
+ this.inFlight--;
59
+ this.settled++;
60
+ }
61
+ }
62
+ }
63
+ /**
64
+ * Wrap every write method `adapter` has so it moves the returned head, and
65
+ * return that head for the adapter's `head()` to read. Call once, from the
66
+ * adapter's own constructor: it wraps the methods present then, so a write
67
+ * method assigned as a field after that call goes uncounted (the
68
+ * conformance suite's head tests catch one).
69
+ */
70
+ export function trackWrites(adapter) {
71
+ const head = new WriteHead();
72
+ const members = adapter;
73
+ for (const name of Object.keys(WRITE_METHODS)) {
74
+ const write = members[name];
75
+ if (typeof write !== 'function')
76
+ continue;
77
+ members[name] = (...args) => head.track(() => write.apply(adapter, args));
78
+ }
79
+ return head;
80
+ }
81
+ /** The head of a store made of two halves: it moves when either does. */
82
+ export function combinedHead(record, blob) {
83
+ return `${record}/${blob}`;
84
+ }
85
+ //# sourceMappingURL=head.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"head.js","sourceRoot":"","sources":["../../src/adapter/head.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH;;;GAGG;AACH,MAAM,aAAa,GAAmC;IACpD,YAAY,EAAE,IAAI;IAClB,YAAY,EAAE,IAAI;IAClB,YAAY,EAAE,IAAI;IAClB,YAAY,EAAE,IAAI;IAClB,cAAc,EAAE,IAAI;IACpB,SAAS,EAAE,IAAI;IACf,WAAW,EAAE,IAAI;IACjB,gBAAgB,EAAE,IAAI;IACtB,eAAe,EAAE,IAAI;IACrB,UAAU,EAAE,IAAI;IAChB,SAAS,EAAE,IAAI;IACf,cAAc,EAAE,IAAI;IACpB,eAAe,EAAE,IAAI;IACrB,QAAQ,EAAE,IAAI;IACd,mCAAmC,EAAE,IAAI;IACzC,OAAO,EAAE,IAAI;IACb,UAAU,EAAE,IAAI;IAChB,yBAAyB,EAAE,IAAI;CAChC,CAAC;AAEF,oDAAoD;AACpD,MAAM,SAAS;IACI,KAAK,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;IACrC,OAAO,GAAG,CAAC,CAAC;IACZ,QAAQ,GAAG,CAAC,CAAC;IACb,SAAS,GAAG,CAAC,CAAC;IAEtB;;;;OAIG;IACH,IAAI;QACF,IAAI,IAAI,CAAC,QAAQ;YAAE,OAAO,GAAG,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,OAAO,IAAI,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC;QAC9E,OAAO,GAAG,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;IACzC,CAAC;IAED,KAAK,CAAC,KAAK,CAAI,KAAuB;QACpC,IAAI,CAAC,QAAQ,EAAE,CAAC;QAChB,IAAI,CAAC;YACH,OAAO,MAAM,KAAK,EAAE,CAAC;QACvB,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,QAAQ,EAAE,CAAC;YAChB,IAAI,CAAC,OAAO,EAAE,CAAC;QACjB,CAAC;IACH,CAAC;CACF;AAKD;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CAAC,OAAe;IACzC,MAAM,IAAI,GAAG,IAAI,SAAS,EAAE,CAAC;IAC7B,MAAM,OAAO,GAAG,OAAkC,CAAC;IACnD,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC;QAC9C,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QAC5B,IAAI,OAAO,KAAK,KAAK,UAAU;YAAE,SAAS;QAC1C,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,IAAe,EAAE,EAAE,CACrC,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAE,KAA+C,CAAC,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;IAC5F,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,YAAY,CAAC,MAAc,EAAE,IAAY;IACvD,OAAO,GAAG,MAAM,IAAI,IAAI,EAAE,CAAC;AAC7B,CAAC"}
@@ -7,9 +7,13 @@
7
7
  * adapters). Types an app reads too, such as StackCapabilities, live in
8
8
  * the root entry point instead: every export has exactly one home.
9
9
  */
10
- export type { AdapterQuery, PlainQuery, AdapterSort, StackAdapter, StackRecordAdapter, StackBlobAdapter, BlobInfo, SnapshotOptions, JournalEntryInput, JournalOptions, MutateOptions, AspectWriteOptions, ElementWriteOptions, Reach, RecordHistory, StoreSeed, } from '../types/index.js';
10
+ export type { AdapterQuery, PlainQuery, AdapterSort, StackAdapter, StackRecordAdapter, StackBlobAdapter, BlobInfo, BlobsQuery, StoreWriters, StoreReadMember, StoreWriteMethod, RecordWriteMethod, BlobWriteMethod, SnapshotOptions, JournalEntryInput, JournalOptions, MutateOptions, AspectWriteOptions, ElementWriteOptions, Reach, RecordHistory, StoreSeed, } from '../types/index.js';
11
11
  export { sameAssociationSet } from '../associations/identity.js';
12
12
  export { ElementSetMovedError, FormatMismatchError, OwnerMismatchError, softDeletedRefusal, } from '../errors.js';
13
+ export { assertFileId, blobWindow } from './blobs.js';
14
+ export { trackWrites, combinedHead } from './head.js';
15
+ export type { WriteHead } from './head.js';
16
+ export { FILE_ID_RE } from '../validate.js';
13
17
  export { combineAdapters } from './combine.js';
14
18
  export { copyStack } from './copy.js';
15
19
  export type { CreateStore } from './copy.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/adapter/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,YAAY,EACV,YAAY,EACZ,UAAU,EACV,WAAW,EACX,YAAY,EACZ,kBAAkB,EAClB,gBAAgB,EAChB,QAAQ,EACR,eAAe,EACf,iBAAiB,EACjB,cAAc,EACd,aAAa,EACb,kBAAkB,EAClB,mBAAmB,EACnB,KAAK,EACL,aAAa,EACb,SAAS,GACV,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,YAAY,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACrC,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EACL,uBAAuB,EACvB,eAAe,EACf,YAAY,EACZ,6BAA6B,EAC7B,uBAAuB,EACvB,wBAAwB,EACxB,cAAc,EACd,qBAAqB,GACtB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,gBAAgB,EAChB,cAAc,EACd,kBAAkB,EAClB,iBAAiB,EACjB,YAAY,GACb,MAAM,WAAW,CAAC;AACnB,YAAY,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/adapter/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,YAAY,EACV,YAAY,EACZ,UAAU,EACV,WAAW,EACX,YAAY,EACZ,kBAAkB,EAClB,gBAAgB,EAChB,QAAQ,EACR,UAAU,EACV,YAAY,EACZ,eAAe,EACf,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,EACf,eAAe,EACf,iBAAiB,EACjB,cAAc,EACd,aAAa,EACb,kBAAkB,EAClB,mBAAmB,EACnB,KAAK,EACL,aAAa,EACb,SAAS,GACV,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACtD,YAAY,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,YAAY,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACrC,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EACL,uBAAuB,EACvB,eAAe,EACf,YAAY,EACZ,6BAA6B,EAC7B,uBAAuB,EACvB,wBAAwB,EACxB,cAAc,EACd,qBAAqB,GACtB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,gBAAgB,EAChB,cAAc,EACd,kBAAkB,EAClB,iBAAiB,EACjB,YAAY,GACb,MAAM,WAAW,CAAC;AACnB,YAAY,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC"}
@@ -9,6 +9,9 @@
9
9
  */
10
10
  export { sameAssociationSet } from '../associations/identity.js';
11
11
  export { ElementSetMovedError, FormatMismatchError, OwnerMismatchError, softDeletedRefusal, } from '../errors.js';
12
+ export { assertFileId, blobWindow } from './blobs.js';
13
+ export { trackWrites, combinedHead } from './head.js';
14
+ export { FILE_ID_RE } from '../validate.js';
12
15
  export { combineAdapters } from './combine.js';
13
16
  export { copyStack } from './copy.js';
14
17
  export { newStoreSeed } from './seed.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/adapter/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAoBH,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAErC,OAAO,EACL,uBAAuB,EACvB,eAAe,EACf,YAAY,EACZ,6BAA6B,EAC7B,uBAAuB,EACvB,wBAAwB,EACxB,cAAc,EACd,qBAAqB,GACtB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,gBAAgB,EAChB,cAAc,EACd,kBAAkB,EAClB,iBAAiB,EACjB,YAAY,GACb,MAAM,WAAW,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/adapter/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AA0BH,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAEtD,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAErC,OAAO,EACL,uBAAuB,EACvB,eAAe,EACf,YAAY,EACZ,6BAA6B,EAC7B,uBAAuB,EACvB,wBAAwB,EACxB,cAAc,EACd,qBAAqB,GACtB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,gBAAgB,EAChB,cAAc,EACd,kBAAkB,EAClB,iBAAiB,EACjB,YAAY,GACb,MAAM,WAAW,CAAC"}
@@ -93,8 +93,8 @@ export declare class Stack implements StackClient {
93
93
  asActor(actor: Actor): ScopedStack;
94
94
  /**
95
95
  * A scoped view needs a stack that owns its storage: one whose adapter
96
- * queries within a reach and relays no changes from elsewhere. A
97
- * server-backed stack is scoped by the session that opened it instead.
96
+ * queries within a reach and is its store's only writer. A server-backed
97
+ * stack is scoped by the session that opened it instead.
98
98
  * See docs/spec/access-control.md § Enforcement: Stack.asEntity().
99
99
  */
100
100
  private scope;
@@ -345,7 +345,7 @@ export declare class Stack implements StackClient {
345
345
  * from.
346
346
  */
347
347
  private openRelay;
348
- /** Whether changes reach this stack from elsewhere. */
348
+ /** Whether a relay can be opened; whether one is needed is `writers`. */
349
349
  private get relaysChanges();
350
350
  /**
351
351
  * Flush pending writes to the underlying storage. A no-op for adapters
@@ -1 +1 @@
1
- {"version":3,"file":"stack.d.ts","sourceRoot":"","sources":["../../src/stack/stack.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"stack.d.ts","sourceRoot":"","sources":["../../src/stack/stack.ts"],"names":[],"mappings":"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"}
@@ -219,8 +219,8 @@ export class Stack {
219
219
  }
220
220
  /**
221
221
  * A scoped view needs a stack that owns its storage: one whose adapter
222
- * queries within a reach and relays no changes from elsewhere. A
223
- * server-backed stack is scoped by the session that opened it instead.
222
+ * queries within a reach and is its store's only writer. A server-backed
223
+ * stack is scoped by the session that opened it instead.
224
224
  * See docs/spec/access-control.md § Enforcement: Stack.asEntity().
225
225
  */
226
226
  scope(principalId, subjectId) {
@@ -231,9 +231,10 @@ export class Stack {
231
231
  "query could not be kept to the requester's reach. Every local adapter must; a " +
232
232
  'server-backed stack is scoped by opening it with the session you mean.');
233
233
  }
234
- if (this.relaysChanges) {
235
- throw new ScopeUnavailableError('This stack cannot be scoped: it relays changes made elsewhere, whose frames were ' +
236
- 'scoped by the session that opened the feed. Open it with the session you mean.');
234
+ if (this.adapter.writers === 'shared') {
235
+ throw new ScopeUnavailableError('This stack cannot be scoped: others write its store, and their changes reach it ' +
236
+ 'scoped by the session that opened the feed, if at all. Open it with the session ' +
237
+ 'you mean.');
237
238
  }
238
239
  return new ScopedStack(scopeToken, {
239
240
  stack: this,
@@ -1098,6 +1099,12 @@ export class Stack {
1098
1099
  */
1099
1100
  async subscribe(handler, opts = {}) {
1100
1101
  this.assertOpen();
1102
+ if (this.adapter.writers === 'shared' && !this.relaysChanges) {
1103
+ throw new StackBadRequestError('subscribe() cannot be served: others write this stack, and its adapter has no ' +
1104
+ "subscribeChanges() to relay their changes, so a stream of this client's own writes " +
1105
+ 'would pass for the whole. Connect to a server that advertises a change feed, or ' +
1106
+ 'poll query().');
1107
+ }
1101
1108
  assertSinceUsable(opts.since, this.relaysChanges);
1102
1109
  assertValidBaseIdFilter(opts.filter);
1103
1110
  const unsubscribe = this.changes.subscribe(handler, opts);
@@ -1138,7 +1145,7 @@ export class Stack {
1138
1145
  void stop();
1139
1146
  };
1140
1147
  }
1141
- /** Whether changes reach this stack from elsewhere. */
1148
+ /** Whether a relay can be opened; whether one is needed is `writers`. */
1142
1149
  get relaysChanges() {
1143
1150
  return typeof this.adapter.subscribeChanges === 'function';
1144
1151
  }