@haverstack/core 0.40.0 → 0.42.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +121 -59
- package/dist/access.d.ts +34 -36
- package/dist/access.d.ts.map +1 -1
- package/dist/access.js +65 -42
- package/dist/access.js.map +1 -1
- package/dist/{combine.d.ts → adapter/combine.d.ts} +8 -1
- package/dist/adapter/combine.d.ts.map +1 -0
- package/dist/{combine.js → adapter/combine.js} +7 -0
- package/dist/adapter/combine.js.map +1 -0
- package/dist/{adapter-entry.d.ts → adapter/index.d.ts} +6 -5
- package/dist/adapter/index.d.ts.map +1 -0
- package/dist/{adapter-entry.js → adapter/index.js} +5 -4
- package/dist/adapter/index.js.map +1 -0
- package/dist/{sort.d.ts → adapter/sort.d.ts} +20 -20
- package/dist/adapter/sort.d.ts.map +1 -0
- package/dist/{sort.js → adapter/sort.js} +37 -27
- package/dist/adapter/sort.js.map +1 -0
- package/dist/associations/identity.d.ts +93 -0
- package/dist/associations/identity.d.ts.map +1 -0
- package/dist/associations/identity.js +198 -0
- package/dist/associations/identity.js.map +1 -0
- package/dist/associations/validation.d.ts +90 -0
- package/dist/associations/validation.d.ts.map +1 -0
- package/dist/associations/validation.js +339 -0
- package/dist/associations/validation.js.map +1 -0
- package/dist/attachment-records.d.ts +48 -0
- package/dist/attachment-records.d.ts.map +1 -0
- package/dist/attachment-records.js +52 -0
- package/dist/attachment-records.js.map +1 -0
- package/dist/collection.d.ts +182 -0
- package/dist/collection.d.ts.map +1 -0
- package/dist/collection.js +407 -0
- package/dist/collection.js.map +1 -0
- package/dist/content-match.d.ts +25 -0
- package/dist/content-match.d.ts.map +1 -0
- package/dist/content-match.js +51 -0
- package/dist/content-match.js.map +1 -0
- package/dist/content-translation.d.ts +42 -0
- package/dist/content-translation.d.ts.map +1 -0
- package/dist/content-translation.js +108 -0
- package/dist/content-translation.js.map +1 -0
- package/dist/did/did.d.ts.map +1 -0
- package/dist/{did.js → did/did.js} +3 -4
- package/dist/did/did.js.map +1 -0
- package/dist/{did-entry.d.ts → did/index.d.ts} +1 -1
- package/dist/did/index.d.ts.map +1 -0
- package/dist/{did-entry.js → did/index.js} +3 -3
- package/dist/did/index.js.map +1 -0
- package/dist/errors.d.ts +36 -63
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +35 -58
- package/dist/errors.js.map +1 -1
- package/dist/grants.d.ts +20 -43
- package/dist/grants.d.ts.map +1 -1
- package/dist/grants.js +71 -134
- package/dist/grants.js.map +1 -1
- package/dist/id.d.ts +13 -31
- package/dist/id.d.ts.map +1 -1
- package/dist/id.js +13 -31
- package/dist/id.js.map +1 -1
- package/dist/index.d.ts +14 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -5
- package/dist/index.js.map +1 -1
- package/dist/install.d.ts +141 -0
- package/dist/install.d.ts.map +1 -0
- package/dist/install.js +219 -0
- package/dist/install.js.map +1 -0
- package/dist/merge.d.ts.map +1 -1
- package/dist/merge.js +5 -11
- package/dist/merge.js.map +1 -1
- package/dist/migration-steps.d.ts +102 -0
- package/dist/migration-steps.d.ts.map +1 -0
- package/dist/migration-steps.js +293 -0
- package/dist/migration-steps.js.map +1 -0
- package/dist/query-validation.d.ts +28 -94
- package/dist/query-validation.d.ts.map +1 -1
- package/dist/query-validation.js +156 -336
- package/dist/query-validation.js.map +1 -1
- package/dist/record-changes.d.ts +2 -117
- package/dist/record-changes.d.ts.map +1 -1
- package/dist/record-changes.js +10 -212
- package/dist/record-changes.js.map +1 -1
- package/dist/schema.d.ts +18 -7
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +59 -30
- package/dist/schema.js.map +1 -1
- package/dist/scoped-stack/authority.d.ts +156 -0
- package/dist/scoped-stack/authority.d.ts.map +1 -0
- package/dist/scoped-stack/authority.js +384 -0
- package/dist/scoped-stack/authority.js.map +1 -0
- package/dist/scoped-stack/scoped-stack.d.ts +338 -0
- package/dist/scoped-stack/scoped-stack.d.ts.map +1 -0
- package/dist/scoped-stack/scoped-stack.js +776 -0
- package/dist/scoped-stack/scoped-stack.js.map +1 -0
- package/dist/scoped-stack/subscription.d.ts +55 -0
- package/dist/scoped-stack/subscription.d.ts.map +1 -0
- package/dist/scoped-stack/subscription.js +110 -0
- package/dist/scoped-stack/subscription.js.map +1 -0
- package/dist/stack/attachments.d.ts +24 -0
- package/dist/stack/attachments.d.ts.map +1 -0
- package/dist/stack/attachments.js +113 -0
- package/dist/stack/attachments.js.map +1 -0
- package/dist/{changes.d.ts → stack/changes.d.ts} +29 -65
- package/dist/stack/changes.d.ts.map +1 -0
- package/dist/{changes.js → stack/changes.js} +32 -66
- package/dist/stack/changes.js.map +1 -0
- package/dist/stack/client.d.ts +271 -0
- package/dist/stack/client.d.ts.map +1 -0
- package/dist/stack/client.js +9 -0
- package/dist/stack/client.js.map +1 -0
- package/dist/stack/identity-bindings.d.ts.map +1 -0
- package/dist/{identity-bindings.js → stack/identity-bindings.js} +8 -14
- package/dist/stack/identity-bindings.js.map +1 -0
- package/dist/stack/install-app.d.ts +22 -0
- package/dist/stack/install-app.d.ts.map +1 -0
- package/dist/stack/install-app.js +260 -0
- package/dist/stack/install-app.js.map +1 -0
- package/dist/stack/integrity.d.ts +94 -0
- package/dist/stack/integrity.d.ts.map +1 -0
- package/dist/stack/integrity.js +268 -0
- package/dist/stack/integrity.js.map +1 -0
- package/dist/{limits.d.ts → stack/limits.d.ts} +2 -5
- package/dist/stack/limits.d.ts.map +1 -0
- package/dist/{limits.js → stack/limits.js} +3 -6
- package/dist/stack/limits.js.map +1 -0
- package/dist/stack/migrations.d.ts +59 -0
- package/dist/stack/migrations.d.ts.map +1 -0
- package/dist/stack/migrations.js +141 -0
- package/dist/stack/migrations.js.map +1 -0
- package/dist/{stack-reads.d.ts → stack/reads.d.ts} +33 -6
- package/dist/stack/reads.d.ts.map +1 -0
- package/dist/{stack-reads.js → stack/reads.js} +49 -7
- package/dist/stack/reads.js.map +1 -0
- package/dist/stack/record-id.d.ts +35 -0
- package/dist/stack/record-id.d.ts.map +1 -0
- package/dist/stack/record-id.js +82 -0
- package/dist/stack/record-id.js.map +1 -0
- package/dist/stack/stack.d.ts +438 -0
- package/dist/stack/stack.d.ts.map +1 -0
- package/dist/stack/stack.js +1366 -0
- package/dist/stack/stack.js.map +1 -0
- package/dist/stack/system-types.d.ts +16 -0
- package/dist/stack/system-types.d.ts.map +1 -0
- package/dist/stack/system-types.js +111 -0
- package/dist/stack/system-types.js.map +1 -0
- package/dist/stack/type-grants.d.ts +20 -0
- package/dist/stack/type-grants.d.ts.map +1 -0
- package/dist/stack/type-grants.js +69 -0
- package/dist/stack/type-grants.js.map +1 -0
- package/dist/stack/write-expectation.d.ts +78 -0
- package/dist/stack/write-expectation.d.ts.map +1 -0
- package/dist/stack/write-expectation.js +71 -0
- package/dist/stack/write-expectation.js.map +1 -0
- package/dist/testing.d.ts +21 -26
- package/dist/testing.d.ts.map +1 -1
- package/dist/testing.js +50 -70
- package/dist/testing.js.map +1 -1
- package/dist/type-handle.d.ts +67 -78
- package/dist/type-handle.d.ts.map +1 -1
- package/dist/type-handle.js +44 -111
- package/dist/type-handle.js.map +1 -1
- package/dist/types/adapter.d.ts +223 -0
- package/dist/types/adapter.d.ts.map +1 -0
- package/dist/types/adapter.js +5 -0
- package/dist/types/adapter.js.map +1 -0
- package/dist/types/associations.d.ts +156 -0
- package/dist/types/associations.d.ts.map +1 -0
- package/dist/types/associations.js +13 -0
- package/dist/types/associations.js.map +1 -0
- package/dist/types/capabilities.d.ts +89 -0
- package/dist/types/capabilities.d.ts.map +1 -0
- package/dist/types/capabilities.js +5 -0
- package/dist/types/capabilities.js.map +1 -0
- package/dist/types/events.d.ts +155 -0
- package/dist/types/events.d.ts.map +1 -0
- package/dist/types/events.js +5 -0
- package/dist/types/events.js.map +1 -0
- package/dist/types/ids.d.ts +43 -0
- package/dist/types/ids.d.ts.map +1 -0
- package/dist/types/ids.js +5 -0
- package/dist/types/ids.js.map +1 -0
- package/dist/types/index.d.ts +19 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +19 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/journal.d.ts +47 -0
- package/dist/types/journal.d.ts.map +1 -0
- package/dist/types/journal.js +5 -0
- package/dist/types/journal.js.map +1 -0
- package/dist/types/query.d.ts +185 -0
- package/dist/types/query.d.ts.map +1 -0
- package/dist/types/query.js +10 -0
- package/dist/types/query.js.map +1 -0
- package/dist/types/records.d.ts +76 -0
- package/dist/types/records.d.ts.map +1 -0
- package/dist/types/records.js +5 -0
- package/dist/types/records.js.map +1 -0
- package/dist/types/schema.d.ts +74 -0
- package/dist/types/schema.d.ts.map +1 -0
- package/dist/types/schema.js +5 -0
- package/dist/types/schema.js.map +1 -0
- package/dist/types/system.d.ts +161 -0
- package/dist/types/system.d.ts.map +1 -0
- package/dist/types/system.js +32 -0
- package/dist/types/system.js.map +1 -0
- package/dist/types/tokens.d.ts +39 -0
- package/dist/types/tokens.d.ts.map +1 -0
- package/dist/types/tokens.js +5 -0
- package/dist/types/tokens.js.map +1 -0
- package/dist/validate.d.ts +29 -70
- package/dist/validate.d.ts.map +1 -1
- package/dist/validate.js +65 -97
- package/dist/validate.js.map +1 -1
- package/dist/{attachment-download.d.ts → wire/attachment-download.d.ts} +0 -57
- package/dist/wire/attachment-download.d.ts.map +1 -0
- package/dist/{attachment-download.js → wire/attachment-download.js} +0 -61
- package/dist/wire/attachment-download.js.map +1 -0
- package/dist/{auth.d.ts → wire/auth.d.ts} +5 -8
- package/dist/wire/auth.d.ts.map +1 -0
- package/dist/{auth.js → wire/auth.js} +5 -8
- package/dist/wire/auth.js.map +1 -0
- package/dist/{wire-body.d.ts → wire/body.d.ts} +13 -5
- package/dist/wire/body.d.ts.map +1 -0
- package/dist/{wire-body.js → wire/body.js} +65 -7
- package/dist/wire/body.js.map +1 -0
- package/dist/{wire-entry.d.ts → wire/index.d.ts} +12 -12
- package/dist/wire/index.d.ts.map +1 -0
- package/dist/{wire-entry.js → wire/index.js} +13 -17
- package/dist/wire/index.js.map +1 -0
- package/dist/{wire-record.d.ts → wire/record.d.ts} +10 -22
- package/dist/wire/record.d.ts.map +1 -0
- package/dist/{wire-record.js → wire/record.js} +12 -24
- package/dist/wire/record.js.map +1 -0
- package/dist/{wire-request.d.ts → wire/request.d.ts} +20 -37
- package/dist/wire/request.d.ts.map +1 -0
- package/dist/{wire-request.js → wire/request.js} +79 -54
- package/dist/wire/request.js.map +1 -0
- package/package.json +7 -7
- package/dist/adapter-entry.d.ts.map +0 -1
- package/dist/adapter-entry.js.map +0 -1
- package/dist/attachment-download.d.ts.map +0 -1
- package/dist/attachment-download.js.map +0 -1
- package/dist/auth.d.ts.map +0 -1
- package/dist/auth.js.map +0 -1
- package/dist/changes.d.ts.map +0 -1
- package/dist/changes.js.map +0 -1
- package/dist/combine.d.ts.map +0 -1
- package/dist/combine.js.map +0 -1
- package/dist/did-entry.d.ts.map +0 -1
- package/dist/did-entry.js.map +0 -1
- package/dist/did.d.ts.map +0 -1
- package/dist/did.js.map +0 -1
- package/dist/identity-bindings.d.ts.map +0 -1
- package/dist/identity-bindings.js.map +0 -1
- package/dist/limits.d.ts.map +0 -1
- package/dist/limits.js.map +0 -1
- package/dist/record-id.d.ts +0 -70
- package/dist/record-id.d.ts.map +0 -1
- package/dist/record-id.js +0 -127
- package/dist/record-id.js.map +0 -1
- package/dist/scoped-stack.d.ts +0 -532
- package/dist/scoped-stack.d.ts.map +0 -1
- package/dist/scoped-stack.js +0 -1219
- package/dist/scoped-stack.js.map +0 -1
- package/dist/sort.d.ts.map +0 -1
- package/dist/sort.js.map +0 -1
- package/dist/stack-reads.d.ts.map +0 -1
- package/dist/stack-reads.js.map +0 -1
- package/dist/stack.d.ts +0 -971
- package/dist/stack.d.ts.map +0 -1
- package/dist/stack.js +0 -2012
- package/dist/stack.js.map +0 -1
- package/dist/types.d.ts +0 -1250
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -49
- package/dist/types.js.map +0 -1
- package/dist/wire-body.d.ts.map +0 -1
- package/dist/wire-body.js.map +0 -1
- package/dist/wire-entry.d.ts.map +0 -1
- package/dist/wire-entry.js.map +0 -1
- package/dist/wire-record.d.ts.map +0 -1
- package/dist/wire-record.js.map +0 -1
- package/dist/wire-request.d.ts.map +0 -1
- package/dist/wire-request.js.map +0 -1
- /package/dist/{did.d.ts → did/did.d.ts} +0 -0
- /package/dist/{identity-bindings.d.ts → stack/identity-bindings.d.ts} +0 -0
package/dist/type-handle.js
CHANGED
|
@@ -2,130 +2,63 @@
|
|
|
2
2
|
* Stack — Type handles
|
|
3
3
|
* -------------------------------------------------------
|
|
4
4
|
* A Type's schema written once as a literal, from which the compiler derives
|
|
5
|
-
* the content type: `ContentOf` for a
|
|
6
|
-
*
|
|
7
|
-
* wherever it has no `defineType()` result.
|
|
5
|
+
* the content type: `ContentOf` for a create, `StoredContentOf` for a read.
|
|
6
|
+
* A handle is a plain value, so `StackClient`
|
|
7
|
+
* code can use it wherever it has no `defineType()` result.
|
|
8
8
|
*
|
|
9
9
|
* The derived types layer over runtime validation, which stays the guarantee.
|
|
10
|
-
*
|
|
11
|
-
*
|
|
10
|
+
* A handle reaches records through `client.collection(handle)`; see
|
|
11
|
+
* collection.ts and docs/spec/data-model.md § Type handles.
|
|
12
12
|
*/
|
|
13
|
-
import { StackBadRequestError,
|
|
14
|
-
import { parseTypeId } from './schema.js';
|
|
13
|
+
import { StackBadRequestError, StackMigrationError } from './errors.js';
|
|
14
|
+
import { lineageProblem, parseTypeId } from './schema.js';
|
|
15
|
+
import { applySteps, fieldOrigins, recordOrigins } from './migration-steps.js';
|
|
15
16
|
/**
|
|
16
|
-
* Name a Type
|
|
17
|
-
*
|
|
18
|
-
* `StackClient`. A handle names exactly
|
|
19
|
-
* argument a call about the whole family
|
|
17
|
+
* Name a Type, its display name, its schema and the version it migrates
|
|
18
|
+
* from in one literal. Pass the result to `defineType()`, a manifest's
|
|
19
|
+
* `types` and `StackClient.collection()`. A handle names exactly
|
|
20
|
+
* one version: `Book.baseId` is the argument a call about the whole family
|
|
21
|
+
* takes.
|
|
20
22
|
*/
|
|
21
|
-
export const typeHandle = (id, schema) => {
|
|
23
|
+
export const typeHandle = ({ id, name, schema, migratesFrom, }) => {
|
|
22
24
|
const parsed = parseTypeId(id);
|
|
23
25
|
if (!parsed) {
|
|
24
26
|
throw new StackBadRequestError(`Invalid TypeId format: "${id}". Expected "namespace/name@version", e.g. "com.example.myapp/note@1".`);
|
|
25
27
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
* Enum values the record holds that the handle's schema does not list. An
|
|
38
|
-
* enum may gain values within a version, so a reader older than the writer
|
|
39
|
-
* can meet one; throwing keeps the derived union exact.
|
|
40
|
-
*/
|
|
41
|
-
const unknownEnumValues = (value, def, path, errors) => {
|
|
42
|
-
if (value === undefined || value === null)
|
|
43
|
-
return;
|
|
44
|
-
if (def.kind === 'string') {
|
|
45
|
-
if (def.enum && typeof value === 'string' && !def.enum.includes(value)) {
|
|
46
|
-
errors.push({
|
|
47
|
-
path,
|
|
48
|
-
message: `Expected one of ${def.enum.map((v) => JSON.stringify(v)).join(', ')}, got ${JSON.stringify(value)}`,
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
if (def.kind === 'array' && !def.open && Array.isArray(value)) {
|
|
54
|
-
value.forEach((item, i) => unknownEnumValues(item, def.items, `${path}[${i}]`, errors));
|
|
55
|
-
return;
|
|
56
|
-
}
|
|
57
|
-
if (def.kind === 'object' && !def.open && typeof value === 'object' && !Array.isArray(value)) {
|
|
58
|
-
walkEnums(value, def.properties, path, errors);
|
|
59
|
-
}
|
|
60
|
-
};
|
|
61
|
-
const walkEnums = (content, schema, prefix, errors) => {
|
|
62
|
-
for (const key of Object.keys(schema)) {
|
|
63
|
-
unknownEnumValues(content[key], schema[key], prefix ? `${prefix}.${key}` : key, errors);
|
|
64
|
-
}
|
|
28
|
+
const from = typeof migratesFrom === 'object' && migratesFrom !== null ? migratesFrom.id : migratesFrom;
|
|
29
|
+
const problem = lineageProblem(id, from);
|
|
30
|
+
if (problem)
|
|
31
|
+
throw new StackBadRequestError(problem);
|
|
32
|
+
return Object.freeze({
|
|
33
|
+
id,
|
|
34
|
+
baseId: parsed.baseId,
|
|
35
|
+
name,
|
|
36
|
+
schema,
|
|
37
|
+
...(from !== undefined && { migratesFrom: from }),
|
|
38
|
+
});
|
|
65
39
|
};
|
|
66
40
|
/**
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
41
|
+
* Build the migration from `from` to `to` out of declared steps, checked
|
|
42
|
+
* against both schemas here so a step the target would refuse fails before
|
|
43
|
+
* any record is written. Within a family, `to` must name `from` as its
|
|
44
|
+
* `migratesFrom`. See docs/spec/data-model.md § Migration steps.
|
|
71
45
|
*/
|
|
72
|
-
export const
|
|
73
|
-
|
|
74
|
-
|
|
46
|
+
export const migration = (from, to, steps) => {
|
|
47
|
+
const refuse = (problem) => new StackMigrationError(`Cannot migrate "${from.id}" to "${to.id}": ${problem}.`);
|
|
48
|
+
if (to.baseId === from.baseId && to.migratesFrom !== from.id) {
|
|
49
|
+
throw refuse(`"${to.id}" migrates from ${to.migratesFrom ? `"${to.migratesFrom}"` : 'nothing'}`);
|
|
75
50
|
}
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
if (
|
|
79
|
-
throw
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
throw new StackBadRequestError('A typed read sees live records only; use the untyped read to include soft-deleted records.');
|
|
86
|
-
}
|
|
87
|
-
};
|
|
88
|
-
export const typedGet = async (client, handle, id) => {
|
|
89
|
-
const record = await client.get(id, { presentAt: 'latest' });
|
|
90
|
-
return record && narrowRecord(handle, record);
|
|
91
|
-
};
|
|
92
|
-
export const typedQuery = async (client, handle, query = {}) => {
|
|
93
|
-
assertLiveFilter(query.filter);
|
|
94
|
-
// The family, not the handle's version: a record still at an older
|
|
95
|
-
// version must be migrated up, or refused as stale, never skipped.
|
|
96
|
-
const result = await client.query({
|
|
97
|
-
...query,
|
|
98
|
-
filter: { ...query.filter, baseId: handle.baseId },
|
|
99
|
-
presentAt: 'latest',
|
|
51
|
+
const frozen = Object.freeze([...steps]);
|
|
52
|
+
const origins = fieldOrigins(frozen, from.schema, to.schema);
|
|
53
|
+
if (typeof origins === 'string')
|
|
54
|
+
throw refuse(origins);
|
|
55
|
+
const built = Object.freeze({
|
|
56
|
+
from: from.id,
|
|
57
|
+
to: to.id,
|
|
58
|
+
steps: frozen,
|
|
59
|
+
migrate: (content) => applySteps(frozen, content),
|
|
100
60
|
});
|
|
101
|
-
|
|
61
|
+
recordOrigins(built, origins);
|
|
62
|
+
return built;
|
|
102
63
|
};
|
|
103
|
-
export const typedCreate = async (client, handle, content, opts) => client.create(handle.id, content, opts);
|
|
104
|
-
export const typedMutate = async (client, handle, id, changes, opts) => {
|
|
105
|
-
// A patch is validated against the record's own stored Type, so one made
|
|
106
|
-
// through a handle for another version would be checked by a schema it
|
|
107
|
-
// was not written for. A missing, unreadable or deleted record is left to
|
|
108
|
-
// mutate(), which refuses it in its own words.
|
|
109
|
-
const current = await client.get(id, { includeDeleted: true });
|
|
110
|
-
if (current && current.typeId !== handle.id) {
|
|
111
|
-
throw new StackBadRequestError(`Record "${id}" is ${current.typeId}, not ${handle.id}`);
|
|
112
|
-
}
|
|
113
|
-
return narrowRecord(handle, await client.mutate(id, changes, opts));
|
|
114
|
-
};
|
|
115
|
-
export const typedSubscribe = (client, handle, handler, opts = {}) =>
|
|
116
|
-
// Exactly the handle's version: an event carries its record as stored, so
|
|
117
|
-
// a subscription cannot migrate it the way a typed read does, and a
|
|
118
|
-
// record of another version has no honest typing here.
|
|
119
|
-
client.subscribe((change) => {
|
|
120
|
-
const { record, ...rest } = change;
|
|
121
|
-
let narrowed;
|
|
122
|
-
try {
|
|
123
|
-
narrowed = record && narrowRecord(handle, record);
|
|
124
|
-
}
|
|
125
|
-
catch (err) {
|
|
126
|
-
if (!(err instanceof StackValidationError))
|
|
127
|
-
throw err;
|
|
128
|
-
}
|
|
129
|
-
handler(narrowed ? { ...rest, record: narrowed } : rest);
|
|
130
|
-
}, { ...opts, filter: { ...opts.filter, typeId: handle.id } });
|
|
131
64
|
//# sourceMappingURL=type-handle.js.map
|
package/dist/type-handle.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"type-handle.js","sourceRoot":"","sources":["../src/type-handle.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,oBAAoB,EAAE,
|
|
1
|
+
{"version":3,"file":"type-handle.js","sourceRoot":"","sources":["../src/type-handle.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AACxE,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1D,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AA4H/E;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,CAAqC,EAC7D,EAAE,EACF,IAAI,EACJ,MAAM,EACN,YAAY,GAMb,EAAiB,EAAE;IAClB,MAAM,MAAM,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC;IAC/B,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,oBAAoB,CAC5B,2BAA2B,EAAE,wEAAwE,CACtG,CAAC;IACJ,CAAC;IACD,MAAM,IAAI,GACR,OAAO,YAAY,KAAK,QAAQ,IAAI,YAAY,KAAK,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC;IAC7F,MAAM,OAAO,GAAG,cAAc,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;IACzC,IAAI,OAAO;QAAE,MAAM,IAAI,oBAAoB,CAAC,OAAO,CAAC,CAAC;IACrD,OAAO,MAAM,CAAC,MAAM,CAAC;QACnB,EAAE;QACF,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,IAAI;QACJ,MAAM;QACN,GAAG,CAAC,IAAI,KAAK,SAAS,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC;KAClD,CAAC,CAAC;AACL,CAAC,CAAC;AAoBF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,CACvB,IAAmB,EACnB,EAAiB,EACjB,KAA4D,EACT,EAAE;IACrD,MAAM,MAAM,GAAG,CAAC,OAAe,EAAE,EAAE,CACjC,IAAI,mBAAmB,CAAC,mBAAmB,IAAI,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,MAAM,OAAO,GAAG,CAAC,CAAC;IACpF,IAAI,EAAE,CAAC,MAAM,KAAK,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC,YAAY,KAAK,IAAI,CAAC,EAAE,EAAE,CAAC;QAC7D,MAAM,MAAM,CACV,IAAI,EAAE,CAAC,EAAE,mBAAmB,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,YAAY,GAAG,CAAC,CAAC,CAAC,SAAS,EAAE,CACnF,CAAC;IACJ,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,KAAK,CAAC,CAA6B,CAAC;IACrE,MAAM,OAAO,GAAG,YAAY,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC;IAC7D,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,MAAM,MAAM,CAAC,OAAO,CAAC,CAAC;IACvD,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC;QAC1B,IAAI,EAAE,IAAI,CAAC,EAAE;QACb,EAAE,EAAE,EAAE,CAAC,EAAE;QACT,KAAK,EAAE,MAAM;QACb,OAAO,EAAE,CAAC,OAAgC,EAAE,EAAE,CAAC,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC;KAC3E,CAAiE,CAAC;IACnE,aAAa,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IAC9B,OAAO,KAAK,CAAC;AACf,CAAC,CAAC"}
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The storage adapter interfaces and the per-call options Stack hands them.
|
|
3
|
+
*/
|
|
4
|
+
import type { AssociationEdit, RecordChangeSet } from './associations.js';
|
|
5
|
+
import type { StackCapabilities } from './capabilities.js';
|
|
6
|
+
import type { RecordChange, Unsubscribe, SubscribeOptions } from './events.js';
|
|
7
|
+
import type { RecordId, TypeId, FileId, AppId, EntityId, Actor } from './ids.js';
|
|
8
|
+
import type { JournalEntryInput, RecordJournalEntry, JournalQuery } from './journal.js';
|
|
9
|
+
import type { StackQuery, QueryResult } from './query.js';
|
|
10
|
+
import type { StackRecord, RecordVersion, VersionsQuery } from './records.js';
|
|
11
|
+
import type { StackType } from './schema.js';
|
|
12
|
+
/**
|
|
13
|
+
* Opt-in optimistic-concurrency precondition. On mismatch the mutation
|
|
14
|
+
* throws StackVersionConflictError and changes nothing; an adapter checks
|
|
15
|
+
* it atomically inside its write. See docs/spec/versioning.md § Optimistic
|
|
16
|
+
* concurrency (`ifVersion`).
|
|
17
|
+
*/
|
|
18
|
+
export type IfVersionOptions = {
|
|
19
|
+
ifVersion?: number;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Accepted by every mutating StackRecordAdapter method. The adapter
|
|
23
|
+
* persists this prior-state snapshot as part of the SAME atomic write as
|
|
24
|
+
* the mutation, so a crash between the two can't leave an orphan versions
|
|
25
|
+
* row. Server-backed adapters (already atomic per-request) can ignore it.
|
|
26
|
+
*/
|
|
27
|
+
export type SnapshotOptions = {
|
|
28
|
+
snapshot?: RecordVersion;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Whether a mutateRecord() call advances `version`/`updatedAt`. `Stack`
|
|
32
|
+
* computes it from what the change set moves; absent means `true`.
|
|
33
|
+
* See docs/spec/versioning.md § Version history.
|
|
34
|
+
*/
|
|
35
|
+
export type BumpVersionOptions = {
|
|
36
|
+
bumpsVersion?: boolean;
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Who is performing a mutation, stamped onto the record in the same write.
|
|
40
|
+
* `ScopedStack` supplies it from the request's identities; a caller of
|
|
41
|
+
* plain `Stack` supplies it only when reconstructing an attributed write.
|
|
42
|
+
* See docs/spec/data-model.md § Authorship and attribution.
|
|
43
|
+
*/
|
|
44
|
+
export type ActorOptions = {
|
|
45
|
+
actor?: Actor;
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* Accepted by every mutating StackRecordAdapter method. The adapter
|
|
49
|
+
* appends the entry, allocating its `seq`, inside the SAME write as the
|
|
50
|
+
* mutation, so a crash cannot leave a change unjournaled.
|
|
51
|
+
*/
|
|
52
|
+
export type JournalOptions = {
|
|
53
|
+
journal?: JournalEntryInput;
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* What every mutating StackRecordAdapter method that bumps `version` takes.
|
|
57
|
+
* mutateRecord() adds BumpVersionOptions and deleteRecord() adds `purge`.
|
|
58
|
+
*/
|
|
59
|
+
export type MutateOptions = IfVersionOptions & SnapshotOptions & ActorOptions & JournalOptions;
|
|
60
|
+
/** The metadata an upload's `_attachment@1` record carries beside its bytes. */
|
|
61
|
+
export type PutAttachmentOptions = {
|
|
62
|
+
mimeType: string;
|
|
63
|
+
filename?: string;
|
|
64
|
+
/** Attribution for the metadata record, as create()'s `appId`. */
|
|
65
|
+
appId?: AppId;
|
|
66
|
+
};
|
|
67
|
+
/**
|
|
68
|
+
* The record-storage half of an adapter: structured data, queries,
|
|
69
|
+
* associations, versioning, type definitions, and stack identity.
|
|
70
|
+
*/
|
|
71
|
+
export interface StackRecordAdapter {
|
|
72
|
+
readonly capabilities: StackCapabilities;
|
|
73
|
+
/** DID of the stack owner. Set during adapter initialization. */
|
|
74
|
+
readonly ownerEntityId: EntityId;
|
|
75
|
+
/**
|
|
76
|
+
* IANA timezone string for this stack, or undefined if never set.
|
|
77
|
+
* Passthrough app metadata with no default — see docs/spec.md § The
|
|
78
|
+
* `_config` record.
|
|
79
|
+
*/
|
|
80
|
+
readonly timezone: string | undefined;
|
|
81
|
+
/**
|
|
82
|
+
* Throws StackConflictError if `record.id` already exists — never a
|
|
83
|
+
* silent overwrite. The check must be atomic with the write (a PK/unique
|
|
84
|
+
* constraint or equivalent); Stack itself doesn't pre-check, so a raw
|
|
85
|
+
* adapter that skips this enforces nothing.
|
|
86
|
+
*/
|
|
87
|
+
createRecord(record: StackRecord, opts?: JournalOptions): Promise<StackRecord>;
|
|
88
|
+
getRecord(id: RecordId): Promise<StackRecord | null>;
|
|
89
|
+
/**
|
|
90
|
+
* Apply a change set in one write — the only multi-aspect atomic write a
|
|
91
|
+
* record has, so a publish cannot half-land. Never touches `typeId`; see
|
|
92
|
+
* commitMigration(). `Stack` validates it and computes `bumpsVersion`,
|
|
93
|
+
* and never hands an adapter a change set that changes nothing.
|
|
94
|
+
* See docs/spec/data-model.md § Mutations.
|
|
95
|
+
*/
|
|
96
|
+
mutateRecord(id: RecordId, changes: RecordChangeSet, opts?: MutateOptions & BumpVersionOptions): Promise<StackRecord>;
|
|
97
|
+
/**
|
|
98
|
+
* Returns the record this call acted on: as it now stands after a soft
|
|
99
|
+
* delete, and as it stood immediately before destruction after a
|
|
100
|
+
* purge — captured inside the same write, so nothing can observe or alter
|
|
101
|
+
* it in between. Null when there was no record to delete, which is the
|
|
102
|
+
* only case that mutates nothing.
|
|
103
|
+
*/
|
|
104
|
+
deleteRecord(id: RecordId, opts?: {
|
|
105
|
+
purge?: boolean;
|
|
106
|
+
} & MutateOptions): Promise<StackRecord | null>;
|
|
107
|
+
/** Reverse a soft delete. Returns the record as it now stands. */
|
|
108
|
+
undeleteRecord(id: RecordId, opts?: MutateOptions): Promise<StackRecord>;
|
|
109
|
+
/**
|
|
110
|
+
* `query.sort`, when present, always carries a `direction`: `Stack`
|
|
111
|
+
* resolves the defaults before any adapter sees the query.
|
|
112
|
+
*/
|
|
113
|
+
queryRecords(query: StackQuery): Promise<QueryResult>;
|
|
114
|
+
/**
|
|
115
|
+
* Apply a list of adds and removes as one write, all or none, removes
|
|
116
|
+
* before adds. Never bumps `version`/`updatedAt` and never snapshots — a
|
|
117
|
+
* set-add composes regardless of write order. A list mixing authority
|
|
118
|
+
* and data elements is refused.
|
|
119
|
+
* See docs/spec/adapters.md § Amending associations.
|
|
120
|
+
*/
|
|
121
|
+
amendAssociations(id: RecordId, changes: AssociationEdit[], opts?: JournalOptions): Promise<StackRecord>;
|
|
122
|
+
/**
|
|
123
|
+
* Snapshots newest first; omitting `query` reads every version.
|
|
124
|
+
* See docs/spec/versioning.md § Version history.
|
|
125
|
+
*/
|
|
126
|
+
getVersions(id: RecordId, query?: VersionsQuery): Promise<RecordVersion[]>;
|
|
127
|
+
getVersion(id: RecordId, version: number): Promise<RecordVersion | null>;
|
|
128
|
+
/**
|
|
129
|
+
* Standalone snapshot write, outside of a mutation's own atomic path.
|
|
130
|
+
* Mutating methods above take a `snapshot` option instead, so the
|
|
131
|
+
* snapshot and the mutation land in one write — see SnapshotOptions.
|
|
132
|
+
*/
|
|
133
|
+
saveVersion(id: RecordId, version: RecordVersion): Promise<void>;
|
|
134
|
+
/**
|
|
135
|
+
* Read a record's change journal, oldest first — required, on the same
|
|
136
|
+
* footing as getVersions(). A recovery mechanism an app cannot rely on is
|
|
137
|
+
* most of the way to no mechanism at all, so an adapter with no journal
|
|
138
|
+
* refuses the call rather than declining to have the method.
|
|
139
|
+
* See docs/spec/journal.md § Reading it.
|
|
140
|
+
*/
|
|
141
|
+
getJournal(id: RecordId, query?: JournalQuery): Promise<RecordJournalEntry[]>;
|
|
142
|
+
/**
|
|
143
|
+
* Restore a record to a previous version's `content` and `typeId` —
|
|
144
|
+
* everything a snapshot carries. Containment, listing and associations
|
|
145
|
+
* are left where they stand, there being nothing to restore them *from*.
|
|
146
|
+
* Bumps version internally; throws StackNotFoundError if the version
|
|
147
|
+
* doesn't exist.
|
|
148
|
+
*/
|
|
149
|
+
restoreVersion(id: RecordId, version: number, opts?: MutateOptions): Promise<StackRecord>;
|
|
150
|
+
/**
|
|
151
|
+
* Commit a migration: write new content under a new typeId in one step.
|
|
152
|
+
* This is the only way a record's typeId changes after creation — used by
|
|
153
|
+
* Stack.commitMigration() and Stack.migrateAll(); Stack.mutate() never
|
|
154
|
+
* changes typeId as a side effect. Bumps version internally.
|
|
155
|
+
*/
|
|
156
|
+
commitMigration(id: RecordId, toTypeId: TypeId, content: Record<string, unknown>, opts?: MutateOptions): Promise<StackRecord>;
|
|
157
|
+
saveType(type: StackType): Promise<void>;
|
|
158
|
+
getType(id: TypeId): Promise<StackType | null>;
|
|
159
|
+
listTypes(): Promise<StackType[]>;
|
|
160
|
+
/**
|
|
161
|
+
* Atomically verify fileId is unreferenced and purge its metadata
|
|
162
|
+
* records, returning them; StackConflictError if still referenced.
|
|
163
|
+
* Optional — Stack.deleteAttachment() has a non-atomic fallback.
|
|
164
|
+
* `metadataTypeIds` is the resolved `_attachment` family, so an adapter
|
|
165
|
+
* needs no baseId concept. See docs/spec/attachments.md § Deleting attachments.
|
|
166
|
+
*/
|
|
167
|
+
deleteUnreferencedAttachmentRecords?(fileId: FileId, metadataTypeIds: TypeId[]): Promise<StackRecord[]>;
|
|
168
|
+
/**
|
|
169
|
+
* Relay changes that originated elsewhere — the inverse direction from
|
|
170
|
+
* `Stack`, which emits every change made through it. Optional, and
|
|
171
|
+
* absent on every local adapter: exactly one process owns a stack's
|
|
172
|
+
* storage, so locally there is no third party whose writes could have
|
|
173
|
+
* been missed. See docs/spec/events.md § Where events come from.
|
|
174
|
+
*/
|
|
175
|
+
subscribeChanges?(opts: SubscribeOptions, handler: (change: RecordChange) => void): Promise<Unsubscribe>;
|
|
176
|
+
flush?(): Promise<void>;
|
|
177
|
+
close?(): Promise<void>;
|
|
178
|
+
}
|
|
179
|
+
/** One stored blob, as reported by StackBlobAdapter.listBlobs(). */
|
|
180
|
+
export type BlobInfo = {
|
|
181
|
+
fileId: FileId;
|
|
182
|
+
size: number;
|
|
183
|
+
/** When the blob was written. Used to apply a GC grace period to fresh, not-yet-associated uploads. */
|
|
184
|
+
modifiedAt: Date;
|
|
185
|
+
};
|
|
186
|
+
/**
|
|
187
|
+
* The blob-storage half of an adapter. Handles raw binary data only;
|
|
188
|
+
* attachment metadata lives on _attachment@1 records in the record adapter.
|
|
189
|
+
*/
|
|
190
|
+
export interface StackBlobAdapter {
|
|
191
|
+
putBlob(data: Uint8Array): Promise<FileId>;
|
|
192
|
+
/**
|
|
193
|
+
* Returns a plain `Uint8Array` (never a subclass such as `Buffer`) that the
|
|
194
|
+
* caller owns: changing it never changes the stored bytes.
|
|
195
|
+
*/
|
|
196
|
+
getBlob(fileId: FileId): Promise<Uint8Array>;
|
|
197
|
+
deleteBlob(fileId: FileId): Promise<void>;
|
|
198
|
+
/**
|
|
199
|
+
* Enumerate every blob currently in storage. Optional — without it,
|
|
200
|
+
* garbage collection can't find bare-bytes orphans (bytes with no
|
|
201
|
+
* metadata record at all). See docs/spec/attachments.md § Garbage
|
|
202
|
+
* collection.
|
|
203
|
+
*/
|
|
204
|
+
listBlobs?(): Promise<BlobInfo[]>;
|
|
205
|
+
flush?(): Promise<void>;
|
|
206
|
+
close?(): Promise<void>;
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* A complete adapter: record storage and blob storage combined.
|
|
210
|
+
* Pass this to Stack.open(). Build one with combineAdapters() when you
|
|
211
|
+
* want different backends for records and blobs (e.g. SQLite + S3).
|
|
212
|
+
*/
|
|
213
|
+
export type StackAdapter = StackRecordAdapter & StackBlobAdapter & {
|
|
214
|
+
/**
|
|
215
|
+
* Store bytes and create the accompanying _attachment@1 record as one
|
|
216
|
+
* atomic operation. Optional; implement only when bytes and records
|
|
217
|
+
* live behind a single boundary (today: APIAdapter alone), and never
|
|
218
|
+
* synthesized by combineAdapters(). A security boundary, not an
|
|
219
|
+
* efficiency shortcut — see docs/spec/adapters.md § Interface split.
|
|
220
|
+
*/
|
|
221
|
+
putAttachmentWithMetadata?(data: Uint8Array, opts: PutAttachmentOptions): Promise<StackRecord>;
|
|
222
|
+
};
|
|
223
|
+
//# sourceMappingURL=adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../src/types/adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.js","sourceRoot":"","sources":["../../src/types/adapter.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Associations: the edges a Record carries, authority and data alike,
|
|
3
|
+
* and the change shapes that move them.
|
|
4
|
+
*/
|
|
5
|
+
import type { RecordId, FileId, EntityId } from './ids.js';
|
|
6
|
+
export type TagAssociation = {
|
|
7
|
+
kind: 'tag';
|
|
8
|
+
label: string;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* `attachmentRecordId` names the `_attachment` record whose upload
|
|
12
|
+
* established this reference — annotation, not identity, since `fileId`
|
|
13
|
+
* alone is what GC, the `referencesFileId` filter and file access ask
|
|
14
|
+
* about. See docs/spec/attachments.md § Naming the upload a reference came from.
|
|
15
|
+
*/
|
|
16
|
+
export type AttachmentAssociation = {
|
|
17
|
+
kind: 'attachment';
|
|
18
|
+
label: string;
|
|
19
|
+
fileId: FileId;
|
|
20
|
+
attachmentRecordId?: RecordId;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* A Record in this stack, or in another one. `stackUrl` is what makes a
|
|
24
|
+
* RecordId meaningful outside the stack that minted it — absent means this
|
|
25
|
+
* stack. See docs/spec/data-model.md § Associations.
|
|
26
|
+
*/
|
|
27
|
+
export type RecordTarget = {
|
|
28
|
+
kind: 'record';
|
|
29
|
+
recordId: RecordId;
|
|
30
|
+
stackUrl?: string;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* A "who" — a DID, which means the same thing in every stack. Group
|
|
34
|
+
* rosters are the canonical use: membership names identities, not records.
|
|
35
|
+
* See docs/spec/identity.md § Group.
|
|
36
|
+
*/
|
|
37
|
+
export type EntityTarget = {
|
|
38
|
+
kind: 'entity';
|
|
39
|
+
entityId: EntityId;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Something outside the stack entirely. `ns` names the scheme that
|
|
43
|
+
* interprets `id` — e.g. "atproto", "activitypub", "email", "url" — so an
|
|
44
|
+
* app selects on it rather than sniffing the identifier.
|
|
45
|
+
* See docs/spec/data-model.md § Relationship targets.
|
|
46
|
+
*/
|
|
47
|
+
export type ExternalTarget = {
|
|
48
|
+
kind: 'external';
|
|
49
|
+
ns: string;
|
|
50
|
+
id: string;
|
|
51
|
+
};
|
|
52
|
+
/** What a relationship association points at. */
|
|
53
|
+
export type RelationshipTarget = RecordTarget | EntityTarget | ExternalTarget;
|
|
54
|
+
export type RelationshipAssociation = {
|
|
55
|
+
kind: 'relationship';
|
|
56
|
+
label: string;
|
|
57
|
+
target: RelationshipTarget;
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* A grant of access to the Record carrying it. The bit is the label, so
|
|
61
|
+
* granting and revoking are a plain add and remove and the element's
|
|
62
|
+
* identity carries its whole meaning. Its grantee shape is its own rather
|
|
63
|
+
* than a `RelationshipTarget`: a target names no role and has no group
|
|
64
|
+
* arm. See docs/spec/access-control.md § Record-level permissions.
|
|
65
|
+
*/
|
|
66
|
+
export type PermissionAssociation = {
|
|
67
|
+
kind: 'permission';
|
|
68
|
+
label: 'read' | 'write';
|
|
69
|
+
grantee: Grantee;
|
|
70
|
+
};
|
|
71
|
+
/** An entity's standing within a `_group` Record's roster. `admin` implies `member` for ACL purposes. */
|
|
72
|
+
export type GroupRole = 'member' | 'admin';
|
|
73
|
+
/**
|
|
74
|
+
* The grantee arms both permission layers share, spelled identically so a
|
|
75
|
+
* value built for one is valid for the other. `role` is required — `member`
|
|
76
|
+
* is the wider set, `admin` the narrower, matching the roster labels where
|
|
77
|
+
* admin implies member. See docs/spec/access-control.md § Who a grant reaches.
|
|
78
|
+
*/
|
|
79
|
+
export type Grantee = {
|
|
80
|
+
kind: 'entity';
|
|
81
|
+
entityId: EntityId;
|
|
82
|
+
} | {
|
|
83
|
+
kind: 'group';
|
|
84
|
+
groupId: RecordId;
|
|
85
|
+
role: GroupRole;
|
|
86
|
+
};
|
|
87
|
+
/**
|
|
88
|
+
* Reach to the world, spelled affirmatively: it names no grantee and
|
|
89
|
+
* carries no bit beyond `read`, so no dropped field on a
|
|
90
|
+
* `PermissionAssociation` can produce it.
|
|
91
|
+
* See docs/spec/access-control.md § Record-level permissions.
|
|
92
|
+
*/
|
|
93
|
+
export type AnyoneAssociation = {
|
|
94
|
+
kind: 'anyone';
|
|
95
|
+
label: 'read';
|
|
96
|
+
};
|
|
97
|
+
/**
|
|
98
|
+
* The authority half of the association table — what the `permissions`
|
|
99
|
+
* field projects. See docs/spec/access-control.md § Record-level
|
|
100
|
+
* permissions.
|
|
101
|
+
*/
|
|
102
|
+
export type AuthorityAssociation = PermissionAssociation | AnyoneAssociation;
|
|
103
|
+
/**
|
|
104
|
+
* The data half — what the `associations` field projects, and the only
|
|
105
|
+
* kinds `associate()`/`dissociate()` accept.
|
|
106
|
+
* See docs/spec/data-model.md § Associations.
|
|
107
|
+
*/
|
|
108
|
+
export type DataAssociation = TagAssociation | AttachmentAssociation | RelationshipAssociation;
|
|
109
|
+
/**
|
|
110
|
+
* Every edge a Record carries, authority and data alike. One shape, one
|
|
111
|
+
* delta and one durability tier; the two halves stay separate call
|
|
112
|
+
* surfaces because they carry different authority.
|
|
113
|
+
* See docs/spec/access-control.md § Record-level permissions.
|
|
114
|
+
*/
|
|
115
|
+
export type Association = DataAssociation | AuthorityAssociation;
|
|
116
|
+
/**
|
|
117
|
+
* One association a write moved, and what it moved from. Each inverse is
|
|
118
|
+
* local to one element, so there is no join key to get wrong; `previous`
|
|
119
|
+
* is carried in full, which is what makes a `repoint` undoable.
|
|
120
|
+
* See docs/spec/journal.md § The entry.
|
|
121
|
+
*/
|
|
122
|
+
export type AssociationChange = {
|
|
123
|
+
op: 'add';
|
|
124
|
+
association: Association;
|
|
125
|
+
} | {
|
|
126
|
+
op: 'repoint';
|
|
127
|
+
association: Association;
|
|
128
|
+
previous: Association;
|
|
129
|
+
} | {
|
|
130
|
+
op: 'remove';
|
|
131
|
+
association: Association;
|
|
132
|
+
};
|
|
133
|
+
/**
|
|
134
|
+
* What a caller sends: the journal's shape without `repoint`, which the
|
|
135
|
+
* journal records and no caller requests. See docs/spec/journal.md § The entry.
|
|
136
|
+
*/
|
|
137
|
+
export type AssociationEdit = Exclude<AssociationChange, {
|
|
138
|
+
op: 'repoint';
|
|
139
|
+
}>;
|
|
140
|
+
/**
|
|
141
|
+
* The aspects of an existing record one mutate() call may move, in any
|
|
142
|
+
* combination. Keys are read for presence: `unlisted: false` is a change,
|
|
143
|
+
* an omitted key is untouched. Each key replaces its aspect whole except
|
|
144
|
+
* `contentPatch`, which merges at the top level (`null` removes).
|
|
145
|
+
* See docs/spec/data-model.md § Mutations.
|
|
146
|
+
*/
|
|
147
|
+
export type RecordChangeSet = {
|
|
148
|
+
contentPatch?: Record<string, unknown | null>;
|
|
149
|
+
parentId?: RecordId | null;
|
|
150
|
+
permissions?: AuthorityAssociation[];
|
|
151
|
+
associations?: DataAssociation[];
|
|
152
|
+
unlisted?: boolean;
|
|
153
|
+
};
|
|
154
|
+
/** The keys of a change set, for presence checks that must not miss one. */
|
|
155
|
+
export declare const RECORD_CHANGE_SET_KEYS: readonly ["contentPatch", "parentId", "permissions", "associations", "unlisted"];
|
|
156
|
+
//# sourceMappingURL=associations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"associations.d.ts","sourceRoot":"","sources":["../../src/types/associations.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Associations: the edges a Record carries, authority and data alike,
|
|
3
|
+
* and the change shapes that move them.
|
|
4
|
+
*/
|
|
5
|
+
/** The keys of a change set, for presence checks that must not miss one. */
|
|
6
|
+
export const RECORD_CHANGE_SET_KEYS = [
|
|
7
|
+
'contentPatch',
|
|
8
|
+
'parentId',
|
|
9
|
+
'permissions',
|
|
10
|
+
'associations',
|
|
11
|
+
'unlisted',
|
|
12
|
+
];
|
|
13
|
+
//# sourceMappingURL=associations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"associations.js","sourceRoot":"","sources":["../../src/types/associations.ts"],"names":[],"mappings":"AAAA;;;GAGG;AA2JH,4EAA4E;AAC5E,MAAM,CAAC,MAAM,sBAAsB,GAAG;IACpC,cAAc;IACd,UAAU;IACV,aAAa;IACb,cAAc;IACd,UAAU;CAC2C,CAAC"}
|